webby 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/History.txt +13 -0
  2. data/Manifest.txt +44 -33
  3. data/Rakefile +2 -2
  4. data/bin/webby +33 -0
  5. data/bin/webby-gen +33 -0
  6. data/examples/presentation/content/presentation/s5/bodybg.gif +0 -0
  7. data/examples/presentation/content/presentation/s5/print.css +25 -1
  8. data/examples/webby/content/release-notes/rel-0-9-3/index.txt +49 -0
  9. data/lib/webby.rb +3 -10
  10. data/lib/webby/apps/generator.rb +41 -48
  11. data/lib/webby/apps/main.rb +22 -0
  12. data/lib/webby/auto_builder.rb +78 -6
  13. data/lib/webby/builder.rb +9 -9
  14. data/lib/webby/core_ext/kernel.rb +5 -0
  15. data/lib/webby/filters/wiki_words.rb +14 -0
  16. data/lib/webby/helpers/url_helper.rb +6 -0
  17. data/lib/webby/journal.rb +126 -0
  18. data/lib/webby/renderer.rb +11 -6
  19. data/lib/webby/resources/meta_file.rb +8 -5
  20. data/lib/webby/stelan/paginator.rb +2 -2
  21. data/lib/webby/tasks/growl.rake +4 -3
  22. data/spec/data/outline/basic.out +81 -0
  23. data/spec/data/outline/basic.txt +25 -0
  24. data/spec/data/outline/no_clobber.out +86 -0
  25. data/spec/data/outline/numbering.out +81 -0
  26. data/spec/data/outline/numbering_only.out +21 -0
  27. data/spec/data/outline/toc_range_1.out +66 -0
  28. data/spec/data/outline/toc_range_2.out +55 -0
  29. data/spec/data/outline/toc_style.out +81 -0
  30. data/spec/data/{Sitefile → site/Sitefile} +0 -0
  31. data/spec/data/{content → site/content}/_partial.txt +0 -0
  32. data/spec/data/{content → site/content}/css/coderay.css +0 -0
  33. data/spec/data/{content → site/content}/css/site.css +0 -0
  34. data/spec/data/{content → site/content}/css/tumblog.css +0 -0
  35. data/spec/data/{content → site/content}/images/tumblog/permalink.gif +0 -0
  36. data/spec/data/{content → site/content}/images/tumblog/rss.gif +0 -0
  37. data/spec/data/{content → site/content}/index.txt +0 -0
  38. data/spec/data/{content → site/content}/photos.txt +0 -0
  39. data/spec/data/{content → site/content}/tumblog/200806/the-noble-chicken/index.txt +0 -0
  40. data/spec/data/{content → site/content}/tumblog/200807/historical-perspectives-on-the-classic-chicken-joke/index.txt +0 -0
  41. data/spec/data/{content → site/content}/tumblog/200807/mad-city-chickens/index.txt +0 -0
  42. data/spec/data/{content → site/content}/tumblog/200807/the-wisdom-of-the-dutch/index.txt +0 -0
  43. data/spec/data/{content → site/content}/tumblog/200807/up-a-tree/index.txt +0 -0
  44. data/spec/data/{content → site/content}/tumblog/index.txt +0 -0
  45. data/spec/data/{content → site/content}/tumblog/rss.txt +0 -0
  46. data/spec/data/{layouts → site/layouts}/default.txt +0 -0
  47. data/spec/data/{layouts → site/layouts}/tumblog/default.txt +0 -0
  48. data/spec/data/{layouts → site/layouts}/tumblog/post.txt +0 -0
  49. data/spec/data/{lib → site/lib}/breadcrumbs.rb +0 -0
  50. data/spec/data/{lib → site/lib}/tumblog_helper.rb +0 -0
  51. data/spec/data/{tasks → site/tasks}/tumblog.rake +0 -0
  52. data/spec/data/{templates → site/templates}/_partial.erb +0 -0
  53. data/spec/data/{templates → site/templates}/atom_feed.erb +0 -0
  54. data/spec/data/{templates → site/templates}/page.erb +0 -0
  55. data/{examples/website → spec/data/site}/templates/presentation.erb +0 -0
  56. data/spec/data/{templates → site/templates}/tumblog/conversation.erb +0 -0
  57. data/spec/data/{templates → site/templates}/tumblog/link.erb +0 -0
  58. data/spec/data/{templates → site/templates}/tumblog/photo.erb +0 -0
  59. data/spec/data/{templates → site/templates}/tumblog/post.erb +0 -0
  60. data/spec/data/{templates → site/templates}/tumblog/quote.erb +0 -0
  61. data/spec/spec_helper.rb +4 -4
  62. data/spec/webby/apps/generator_spec.rb +3 -2
  63. data/spec/webby/filters/basepath_spec.rb +167 -0
  64. data/spec/webby/filters/outline_spec.rb +92 -0
  65. data/spec/webby/renderer_spec.rb +1 -1
  66. data/spec/webby/resources/db_spec.rb +1 -1
  67. data/spec/webby/resources/layout_spec.rb +1 -1
  68. data/spec/webby/resources/meta_file_spec.rb +27 -13
  69. data/spec/webby/resources/page_spec.rb +1 -1
  70. data/spec/webby/resources/resource_spec.rb +1 -1
  71. data/spec/webby/resources_spec.rb +1 -1
  72. data/tasks/gem.rake +93 -32
  73. data/tasks/manifest.rake +3 -4
  74. data/tasks/rubyforge.rake +2 -4
  75. metadata +67 -56
  76. data/lib/webby/tasks/heel.rake +0 -28
  77. data/spec/data/templates/presentation.erb +0 -40
@@ -12,10 +12,13 @@ class Main
12
12
  self.new.run args
13
13
  end
14
14
 
15
+ attr_reader :cmd_line_options
16
+
15
17
  # Create a new Main webby object for building websites.
16
18
  #
17
19
  def initialize
18
20
  @stdout = $stdout
21
+ @cmd_line_options = {}
19
22
  end
20
23
 
21
24
  # Runs the main webby application. The command line arguments are passed
@@ -44,6 +47,16 @@ class Main
44
47
  opts.on(*options)
45
48
  end
46
49
 
50
+ opts.separator ''
51
+ opts.separator 'autobuild options:'
52
+
53
+ opts.on('--web-server', 'Start a local web server') {
54
+ cmd_line_options[:use_web_server] = true
55
+ }
56
+ opts.on('--no-web-server', 'Do not start a local web server') {
57
+ cmd_line_options[:use_web_server] = false
58
+ }
59
+
47
60
  opts.separator ''
48
61
  opts.separator 'common options:'
49
62
 
@@ -98,6 +111,7 @@ class Main
98
111
  def rake
99
112
  app.init 'webby'
100
113
  app.load_rakefile
114
+ load_command_line_options
101
115
  app.top_level
102
116
  end
103
117
 
@@ -167,6 +181,14 @@ class Main
167
181
  args
168
182
  end
169
183
 
184
+ # Load options from the command line into the ::Webby.site struct
185
+ #
186
+ def load_command_line_options
187
+ cmd_line_options.each do |key, value|
188
+ ::Webby.site.__send__("#{key}=", value)
189
+ end
190
+ end
191
+
170
192
  end # class Main
171
193
  end # module Webby::Apps
172
194
 
@@ -1,4 +1,6 @@
1
1
  require 'directory_watcher'
2
+ require 'launchy'
3
+ require 'webrick'
2
4
 
3
5
  module Webby
4
6
 
@@ -21,13 +23,15 @@ class AutoBuilder
21
23
  self.new.run
22
24
  end
23
25
 
26
+ attr_reader :logger
27
+
24
28
  # call-seq:
25
29
  # AutoBuilder.new
26
30
  #
27
31
  # Create a new AutoBuilder class.
28
32
  #
29
33
  def initialize
30
- @log = Logging::Logger[self]
34
+ @logger = Logging::Logger[self]
31
35
 
32
36
  @builder = Builder.new
33
37
  @builder.load_files
@@ -39,6 +43,8 @@ class AutoBuilder
39
43
  glob << File.join(::Webby.site.layout_dir, '**', '*')
40
44
  glob << File.join(::Webby.site.content_dir, '**', '*')
41
45
  @watcher.glob = glob
46
+
47
+ @web_server = ::Webby.site.use_web_server ? WebServer.new : nil
42
48
  end
43
49
 
44
50
  # call-seq:
@@ -53,15 +59,16 @@ class AutoBuilder
53
59
  return if ary.empty?
54
60
 
55
61
  ary.each do |evt|
56
- @log.debug "changed #{evt.path}"
62
+ logger.debug "changed #{evt.path}"
57
63
  next unless test ?f, evt.path
58
64
  next if evt.path =~ ::Webby.exclude
59
65
  Resources.new evt.path
60
66
  end
61
67
 
62
- @builder.run :load_files => false
68
+ logger.info 'running the build'
69
+ @builder.run :load_files => false, :verbose => false
63
70
  rescue => err
64
- @log.error err
71
+ logger.error err
65
72
  end
66
73
 
67
74
  # call-seq:
@@ -71,14 +78,79 @@ class AutoBuilder
71
78
  # Ctrl-C to stop the watcher thread.
72
79
  #
73
80
  def run
74
- @log.info 'starting autobuild (Ctrl-C to stop)'
81
+ logger.info 'starting autobuild (Ctrl-C to stop)'
75
82
 
76
- Signal.trap('INT') {@watcher.stop}
83
+ Signal.trap('INT') {
84
+ @watcher.stop
85
+ @web_server.stop if @web_server
86
+ }
77
87
 
78
88
  @watcher.start
89
+ if @web_server
90
+ @web_server.start
91
+ sleep 0.25
92
+ Launchy.open("http://localhost:#{::Webby.site.heel_port}")
93
+ end
94
+
79
95
  @watcher.join
96
+ @web_server.join if @web_server
80
97
  end
81
98
 
99
+ # Wrapper class around the webrick web server.
100
+ #
101
+ class WebServer
102
+
103
+ # Create a new webrick server configured to serve pages from the output
104
+ # directory. Output will be directed to /dev/null.
105
+ #
106
+ def initialize
107
+ logger = WEBrick::Log.new(Kernel::DEV_NULL, WEBrick::Log::DEBUG)
108
+ access_log = [[ logger, WEBrick::AccessLog::COMBINED_LOG_FORMAT ]]
109
+
110
+ @thread = nil
111
+ @running = false
112
+ @server = WEBrick::HTTPServer.new(
113
+ :BindAddress => 'localhost',
114
+ :Port => ::Webby.site.heel_port,
115
+ :DocumentRoot => ::Webby.site.output_dir,
116
+ :FancyIndexing => true,
117
+ :Logger => logger,
118
+ :AccessLog => access_log
119
+ )
120
+ end
121
+
122
+ # Returns +true+ if the server is running.
123
+ #
124
+ def running?
125
+ @running
126
+ end
127
+
128
+ # Start the webrick server running in a separate thread (so we don't
129
+ # block forever).
130
+ #
131
+ def start
132
+ return if running?
133
+ @running = true
134
+ @thread = Thread.new {@server.start}
135
+ end
136
+
137
+ # Stop the webrick server.
138
+ #
139
+ def stop
140
+ return if not running?
141
+ @running = false
142
+ @server.shutdown
143
+ end
144
+
145
+ # Join on the webserver thread.
146
+ #
147
+ def join
148
+ return if not running?
149
+ @thread.join
150
+ end
151
+
152
+ end # class WebServer
153
+
82
154
  end # class AutoBuilder
83
155
  end # module Webby
84
156
 
@@ -82,7 +82,6 @@ class Builder
82
82
  [args.page, args.title, args.dir]
83
83
  end
84
84
 
85
-
86
85
  private
87
86
 
88
87
  # Returns the binding in the scope of the Builder class object.
@@ -98,7 +97,7 @@ class Builder
98
97
  # layout directories.
99
98
  #
100
99
  def initialize
101
- @log = Logging::Logger[self]
100
+ @logger = Logging::Logger[self]
102
101
  end
103
102
 
104
103
  # call-seq:
@@ -125,24 +124,25 @@ class Builder
125
124
  #
126
125
  def run( opts = {} )
127
126
  opts[:load_files] = true unless opts.has_key?(:load_files)
127
+ verbose = opts.getopt(:verbose, true)
128
128
 
129
129
  unless test(?d, output_dir)
130
- @log.info "creating #{output_dir}"
130
+ journal.create output_dir
131
131
  FileUtils.mkdir output_dir
132
132
  end
133
133
 
134
134
  load_files if opts[:load_files]
135
135
 
136
136
  Resources.pages.each do |page|
137
- next unless page.dirty? or opts[:rebuild]
138
-
139
- @log.info "creating #{page.destination}"
140
-
141
- # make sure the directory exists
142
- FileUtils.mkdir_p ::File.dirname(page.destination)
137
+ unless page.dirty? or opts[:rebuild]
138
+ journal.identical(page.destination) if verbose
139
+ next
140
+ end
143
141
 
144
142
  # copy the resource to the output directory if it is static
145
143
  if page.instance_of? Resources::Static
144
+ FileUtils.mkdir_p ::File.dirname(page.destination)
145
+ journal.create_or_update(page)
146
146
  FileUtils.cp page.path, page.destination
147
147
  FileUtils.chmod 0644, page.destination
148
148
 
@@ -16,6 +16,11 @@ module Kernel
16
16
  STDERR.reopen io.last
17
17
  $stdout, $stderr = STDOUT, STDERR
18
18
  end
19
+
20
+ def journal
21
+ @journal ||= ::Webby::Journal.new
22
+ end
23
+
19
24
  end # module Kernel
20
25
 
21
26
  # EOF
@@ -0,0 +1,14 @@
1
+
2
+ Webby::Filters.register :wikiwords do |input, cursor|
3
+
4
+ renderer = cursor.renderer
5
+ input.gsub %r/\[\[([^\]]+)\]\]/ do
6
+ name = $1
7
+ renderer.link_to_page(name) {
8
+ %Q(<a class="missing internal">#{name}</a>)
9
+ }
10
+ end
11
+
12
+ end
13
+
14
+ # EOF
@@ -159,6 +159,9 @@ module UrlHelper
159
159
  #
160
160
  def link_to_page( *args )
161
161
  self.link_to(*_find_page(args))
162
+ rescue ::Webby::Error => err
163
+ return yield if block_given?
164
+ raise err
162
165
  end
163
166
 
164
167
  # call-seq:
@@ -184,6 +187,9 @@ module UrlHelper
184
187
  return name if @page == page
185
188
 
186
189
  self.link_to(name, page, link_opts)
190
+ rescue ::Webby::Error => err
191
+ return yield if block_given?
192
+ raise err
187
193
  end
188
194
 
189
195
 
@@ -0,0 +1,126 @@
1
+
2
+ module Webby
3
+
4
+ # The Journal class is used to output simple messages regarding the creation
5
+ # and updating of files when webby applications are run. The output messages
6
+ # will be color coded if the terminal supports the ANSI codes.
7
+ #
8
+ class Journal
9
+
10
+ attr_accessor :colorize
11
+ attr_reader :logger
12
+
13
+ # Create a new journal
14
+ #
15
+ def initialize
16
+ @logger = ::Logging::Logger[self]
17
+ @colorize = ENV.has_key?('TERM')
18
+ end
19
+
20
+ # Output a message of the given _type_ using the option _color_ code. The
21
+ # available codes are as follows:
22
+ #
23
+ # * black
24
+ # * red
25
+ # * green
26
+ # * yellow
27
+ # * blue
28
+ # * magenta
29
+ # * cyan
30
+ # * white
31
+ #
32
+ # The color is specified as a string or a symbol.
33
+ #
34
+ def typed_message( type, msg, color = nil )
35
+ type = type.to_s.rjust(13)
36
+ type = self.send(color, type) unless color.nil?
37
+ logger.info "#{type} #{msg.to_s}"
38
+ end
39
+
40
+ # Output a "create" message or an "update" message depending on whether
41
+ # the given _page_ already has a generated output file or not.
42
+ #
43
+ def create_or_update( page )
44
+ if test(?e, page.destination)
45
+ update(page.destination)
46
+ else
47
+ create(page.destination)
48
+ end
49
+ end
50
+
51
+ # Output a create message.
52
+ #
53
+ def create( msg )
54
+ typed_message('create', msg, (colorize ? :green : nil))
55
+ end
56
+
57
+ # Output an update message.
58
+ #
59
+ def update( msg )
60
+ typed_message('update', msg, (colorize ? :yellow : nil))
61
+ end
62
+
63
+ # Output a force message.
64
+ #
65
+ def force( msg )
66
+ typed_message('force', msg, (colorize ? :red : nil))
67
+ end
68
+
69
+ # Output a skip message.
70
+ #
71
+ def skip( msg )
72
+ typed_message('skip', msg, (colorize ? :yellow : nil))
73
+ end
74
+
75
+ # Output an exists message.
76
+ #
77
+ def exists( msg )
78
+ typed_message('exists', msg, (colorize ? :cyan : nil))
79
+ end
80
+
81
+ # Output an identical message.
82
+ #
83
+ def identical( msg )
84
+ typed_message('identical', msg, (colorize ? :cyan : nil))
85
+ end
86
+
87
+ [ [ :clear , 0 ],
88
+ [ :reset , 0 ], # synonym for :clear
89
+ [ :bold , 1 ],
90
+ [ :dark , 2 ],
91
+ [ :italic , 3 ], # not widely implemented
92
+ [ :underline , 4 ],
93
+ [ :underscore , 4 ], # synonym for :underline
94
+ [ :blink , 5 ],
95
+ [ :rapid_blink , 6 ], # not widely implemented
96
+ [ :negative , 7 ], # no reverse because of String#reverse
97
+ [ :concealed , 8 ],
98
+ [ :strikethrough, 9 ], # not widely implemented
99
+ [ :black , 30 ],
100
+ [ :red , 31 ],
101
+ [ :green , 32 ],
102
+ [ :yellow , 33 ],
103
+ [ :blue , 34 ],
104
+ [ :magenta , 35 ],
105
+ [ :cyan , 36 ],
106
+ [ :white , 37 ],
107
+ [ :on_black , 40 ],
108
+ [ :on_red , 41 ],
109
+ [ :on_green , 42 ],
110
+ [ :on_yellow , 43 ],
111
+ [ :on_blue , 44 ],
112
+ [ :on_magenta , 45 ],
113
+ [ :on_cyan , 46 ],
114
+ [ :on_white , 47 ] ].each do |name,code|
115
+
116
+ class_eval <<-CODE
117
+ def #{name.to_s}( str )
118
+ "\e[#{code}m\#{str}\e[0m"
119
+ end
120
+ CODE
121
+ end
122
+
123
+ end # class Journal
124
+ end # module Webby
125
+
126
+ # EOF
@@ -36,6 +36,9 @@ class Renderer
36
36
  renderer = self.new(page)
37
37
 
38
38
  loop {
39
+ FileUtils.mkdir_p ::File.dirname(page.destination)
40
+ journal.create_or_update(page)
41
+
39
42
  ::File.open(page.destination, 'w') do |fd|
40
43
  fd.write(renderer._layout_page)
41
44
  end
@@ -43,6 +46,8 @@ class Renderer
43
46
  }
44
47
  end
45
48
 
49
+ attr_reader :logger
50
+
46
51
  # call-seq:
47
52
  # Renderer.new( page )
48
53
  #
@@ -64,7 +69,7 @@ class Renderer
64
69
 
65
70
  @_bindings = []
66
71
  @_content_for = {}
67
- @log = Logging::Logger[self]
72
+ @logger = Logging::Logger[self]
68
73
  end
69
74
 
70
75
  # call-seq:
@@ -227,11 +232,11 @@ class Renderer
227
232
 
228
233
  @content
229
234
  rescue ::Webby::Error => err
230
- @log.error "while rendering page '#{@page.path}'"
231
- @log.error err.message
235
+ logger.error "while rendering page '#{@page.path}'"
236
+ logger.error err.message
232
237
  rescue => err
233
- @log.error "while rendering page '#{@page.path}'"
234
- @log.fatal err
238
+ logger.error "while rendering page '#{@page.path}'"
239
+ logger.fatal err
235
240
  exit 1
236
241
  ensure
237
242
  @content = nil
@@ -271,7 +276,7 @@ class Renderer
271
276
  @_content_for.clear
272
277
  @_bindings.clear
273
278
  else
274
- @pager.pager.done
279
+ @pager.pager.reset
275
280
  @pager = nil
276
281
  return false
277
282
  end