webby 0.9.3-x86-mswin32

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 (229) hide show
  1. data/History.txt +206 -0
  2. data/Manifest.txt +228 -0
  3. data/README.txt +92 -0
  4. data/Rakefile +49 -0
  5. data/bin/webby +41 -0
  6. data/bin/webby-gen +41 -0
  7. data/examples/blog/Sitefile +7 -0
  8. data/examples/blog/tasks/blog.rake +72 -0
  9. data/examples/blog/templates/atom_feed.erb +40 -0
  10. data/examples/blog/templates/blog/month.erb +22 -0
  11. data/examples/blog/templates/blog/post.erb +16 -0
  12. data/examples/blog/templates/blog/year.erb +22 -0
  13. data/examples/presentation/Sitefile +10 -0
  14. data/examples/presentation/content/css/uv/twilight.css +137 -0
  15. data/examples/presentation/content/presentation/_sample_code.txt +10 -0
  16. data/examples/presentation/content/presentation/index.txt +63 -0
  17. data/examples/presentation/content/presentation/s5/blank.gif +0 -0
  18. data/examples/presentation/content/presentation/s5/bodybg.gif +0 -0
  19. data/examples/presentation/content/presentation/s5/framing.css +23 -0
  20. data/examples/presentation/content/presentation/s5/iepngfix.htc +42 -0
  21. data/examples/presentation/content/presentation/s5/opera.css +7 -0
  22. data/examples/presentation/content/presentation/s5/outline.css +15 -0
  23. data/examples/presentation/content/presentation/s5/pretty.css +86 -0
  24. data/examples/presentation/content/presentation/s5/print.css +25 -0
  25. data/examples/presentation/content/presentation/s5/s5-core.css +9 -0
  26. data/examples/presentation/content/presentation/s5/slides.css +3 -0
  27. data/examples/presentation/content/presentation/s5/slides.js +553 -0
  28. data/examples/presentation/layouts/presentation.txt +43 -0
  29. data/examples/presentation/templates/_code_partial.erb +13 -0
  30. data/examples/presentation/templates/presentation.erb +40 -0
  31. data/examples/tumblog/Sitefile +9 -0
  32. data/examples/tumblog/content/css/tumblog.css +308 -0
  33. data/examples/tumblog/content/images/tumblog/permalink.gif +0 -0
  34. data/examples/tumblog/content/images/tumblog/rss.gif +0 -0
  35. data/examples/tumblog/content/tumblog/200806/the-noble-chicken/index.txt +12 -0
  36. data/examples/tumblog/content/tumblog/200807/historical-perspectives-on-the-classic-chicken-joke/index.txt +12 -0
  37. data/examples/tumblog/content/tumblog/200807/mad-city-chickens/index.txt +10 -0
  38. data/examples/tumblog/content/tumblog/200807/the-wisdom-of-the-dutch/index.txt +11 -0
  39. data/examples/tumblog/content/tumblog/200807/up-a-tree/index.txt +13 -0
  40. data/examples/tumblog/content/tumblog/index.txt +37 -0
  41. data/examples/tumblog/content/tumblog/rss.txt +37 -0
  42. data/examples/tumblog/layouts/tumblog/default.txt +44 -0
  43. data/examples/tumblog/layouts/tumblog/post.txt +15 -0
  44. data/examples/tumblog/lib/tumblog_helper.rb +32 -0
  45. data/examples/tumblog/tasks/tumblog.rake +30 -0
  46. data/examples/tumblog/templates/atom_feed.erb +40 -0
  47. data/examples/tumblog/templates/tumblog/conversation.erb +12 -0
  48. data/examples/tumblog/templates/tumblog/link.erb +10 -0
  49. data/examples/tumblog/templates/tumblog/photo.erb +13 -0
  50. data/examples/tumblog/templates/tumblog/post.erb +12 -0
  51. data/examples/tumblog/templates/tumblog/quote.erb +11 -0
  52. data/examples/webby/Sitefile +19 -0
  53. data/examples/webby/content/communicate/index.txt +28 -0
  54. data/examples/webby/content/css/background.gif +0 -0
  55. data/examples/webby/content/css/blueprint/print.css +76 -0
  56. data/examples/webby/content/css/blueprint/screen.css +696 -0
  57. data/examples/webby/content/css/coderay.css +96 -0
  58. data/examples/webby/content/css/site.css +196 -0
  59. data/examples/webby/content/css/uv/twilight.css +137 -0
  60. data/examples/webby/content/index.txt +37 -0
  61. data/examples/webby/content/learn/index.txt +28 -0
  62. data/examples/webby/content/reference/index.txt +204 -0
  63. data/examples/webby/content/release-notes/index.txt +21 -0
  64. data/examples/webby/content/release-notes/rel-0-9-0/index.txt +74 -0
  65. data/examples/webby/content/release-notes/rel-0-9-1/index.txt +93 -0
  66. data/examples/webby/content/release-notes/rel-0-9-2/index.txt +14 -0
  67. data/examples/webby/content/release-notes/rel-0-9-3/index.txt +49 -0
  68. data/examples/webby/content/robots.txt +6 -0
  69. data/examples/webby/content/script/jquery.corner.js +152 -0
  70. data/examples/webby/content/script/jquery.js +31 -0
  71. data/examples/webby/content/sitemap.txt +31 -0
  72. data/examples/webby/content/tips_and_tricks/index.txt +97 -0
  73. data/examples/webby/content/tutorial/index.txt +135 -0
  74. data/examples/webby/content/user-manual/index.txt +419 -0
  75. data/examples/webby/layouts/default.txt +49 -0
  76. data/examples/webby/templates/page.erb +10 -0
  77. data/examples/website/Sitefile +7 -0
  78. data/examples/website/content/css/blueprint/License.txt +21 -0
  79. data/examples/website/content/css/blueprint/Readme.txt +100 -0
  80. data/examples/website/content/css/blueprint/compressed/print.css +76 -0
  81. data/examples/website/content/css/blueprint/compressed/screen.css +696 -0
  82. data/examples/website/content/css/blueprint/lib/forms.css +45 -0
  83. data/examples/website/content/css/blueprint/lib/grid.css +193 -0
  84. data/examples/website/content/css/blueprint/lib/grid.png +0 -0
  85. data/examples/website/content/css/blueprint/lib/ie.css +30 -0
  86. data/examples/website/content/css/blueprint/lib/reset.css +39 -0
  87. data/examples/website/content/css/blueprint/lib/typography.css +116 -0
  88. data/examples/website/content/css/blueprint/plugins/buttons/Readme +31 -0
  89. data/examples/website/content/css/blueprint/plugins/buttons/buttons.css +97 -0
  90. data/examples/website/content/css/blueprint/plugins/buttons/icons/cross.png +0 -0
  91. data/examples/website/content/css/blueprint/plugins/buttons/icons/key.png +0 -0
  92. data/examples/website/content/css/blueprint/plugins/buttons/icons/tick.png +0 -0
  93. data/examples/website/content/css/blueprint/plugins/css-classes/Readme +14 -0
  94. data/examples/website/content/css/blueprint/plugins/css-classes/css-classes.css +24 -0
  95. data/examples/website/content/css/blueprint/plugins/fancy-type/Readme +22 -0
  96. data/examples/website/content/css/blueprint/plugins/fancy-type/fancy-type-compressed.css +5 -0
  97. data/examples/website/content/css/blueprint/plugins/fancy-type/fancy-type.css +74 -0
  98. data/examples/website/content/css/blueprint/print.css +68 -0
  99. data/examples/website/content/css/blueprint/screen.css +22 -0
  100. data/examples/website/content/css/coderay.css +111 -0
  101. data/examples/website/content/css/site.css +67 -0
  102. data/examples/website/content/index.txt +19 -0
  103. data/examples/website/layouts/default.txt +58 -0
  104. data/examples/website/lib/breadcrumbs.rb +28 -0
  105. data/examples/website/templates/_partial.erb +10 -0
  106. data/examples/website/templates/page.erb +18 -0
  107. data/lib/webby.rb +221 -0
  108. data/lib/webby/apps.rb +12 -0
  109. data/lib/webby/apps/generator.rb +276 -0
  110. data/lib/webby/apps/main.rb +255 -0
  111. data/lib/webby/auto_builder.rb +157 -0
  112. data/lib/webby/builder.rb +180 -0
  113. data/lib/webby/core_ext/enumerable.rb +11 -0
  114. data/lib/webby/core_ext/hash.rb +28 -0
  115. data/lib/webby/core_ext/kernel.rb +26 -0
  116. data/lib/webby/core_ext/string.rb +163 -0
  117. data/lib/webby/core_ext/time.rb +9 -0
  118. data/lib/webby/filters.rb +83 -0
  119. data/lib/webby/filters/basepath.rb +97 -0
  120. data/lib/webby/filters/erb.rb +9 -0
  121. data/lib/webby/filters/haml.rb +18 -0
  122. data/lib/webby/filters/markdown.rb +16 -0
  123. data/lib/webby/filters/outline.rb +309 -0
  124. data/lib/webby/filters/sass.rb +17 -0
  125. data/lib/webby/filters/slides.rb +56 -0
  126. data/lib/webby/filters/textile.rb +16 -0
  127. data/lib/webby/filters/tidy.rb +76 -0
  128. data/lib/webby/filters/wiki_words.rb +14 -0
  129. data/lib/webby/helpers.rb +30 -0
  130. data/lib/webby/helpers/capture_helper.rb +141 -0
  131. data/lib/webby/helpers/coderay_helper.rb +69 -0
  132. data/lib/webby/helpers/graphviz_helper.rb +136 -0
  133. data/lib/webby/helpers/tag_helper.rb +65 -0
  134. data/lib/webby/helpers/tex_img_helper.rb +133 -0
  135. data/lib/webby/helpers/ultraviolet_helper.rb +63 -0
  136. data/lib/webby/helpers/url_helper.rb +241 -0
  137. data/lib/webby/journal.rb +126 -0
  138. data/lib/webby/link_validator.rb +152 -0
  139. data/lib/webby/renderer.rb +386 -0
  140. data/lib/webby/resources.rb +136 -0
  141. data/lib/webby/resources/db.rb +251 -0
  142. data/lib/webby/resources/layout.rb +54 -0
  143. data/lib/webby/resources/meta_file.rb +211 -0
  144. data/lib/webby/resources/page.rb +81 -0
  145. data/lib/webby/resources/partial.rb +85 -0
  146. data/lib/webby/resources/resource.rb +201 -0
  147. data/lib/webby/resources/static.rb +36 -0
  148. data/lib/webby/stelan/mktemp.rb +135 -0
  149. data/lib/webby/stelan/paginator.rb +165 -0
  150. data/lib/webby/stelan/spawner.rb +339 -0
  151. data/lib/webby/tasks/build.rake +27 -0
  152. data/lib/webby/tasks/create.rake +22 -0
  153. data/lib/webby/tasks/deploy.rake +22 -0
  154. data/lib/webby/tasks/growl.rake +16 -0
  155. data/lib/webby/tasks/validate.rake +19 -0
  156. data/spec/core_ext/hash_spec.rb +47 -0
  157. data/spec/core_ext/string_spec.rb +110 -0
  158. data/spec/core_ext/time_spec.rb +19 -0
  159. data/spec/data/hooligans/bad_meta_data_1.txt +34 -0
  160. data/spec/data/hooligans/bad_meta_data_2.txt +34 -0
  161. data/spec/data/outline/basic.out +81 -0
  162. data/spec/data/outline/basic.txt +25 -0
  163. data/spec/data/outline/no_clobber.out +86 -0
  164. data/spec/data/outline/numbering.out +81 -0
  165. data/spec/data/outline/numbering_only.out +21 -0
  166. data/spec/data/outline/toc_range_1.out +66 -0
  167. data/spec/data/outline/toc_range_2.out +55 -0
  168. data/spec/data/outline/toc_style.out +81 -0
  169. data/spec/data/site/Sitefile +9 -0
  170. data/spec/data/site/content/_partial.txt +10 -0
  171. data/spec/data/site/content/css/coderay.css +111 -0
  172. data/spec/data/site/content/css/site.css +67 -0
  173. data/spec/data/site/content/css/tumblog.css +308 -0
  174. data/spec/data/site/content/images/tumblog/permalink.gif +0 -0
  175. data/spec/data/site/content/images/tumblog/rss.gif +0 -0
  176. data/spec/data/site/content/index.txt +19 -0
  177. data/spec/data/site/content/photos.txt +21 -0
  178. data/spec/data/site/content/tumblog/200806/the-noble-chicken/index.txt +12 -0
  179. data/spec/data/site/content/tumblog/200807/historical-perspectives-on-the-classic-chicken-joke/index.txt +12 -0
  180. data/spec/data/site/content/tumblog/200807/mad-city-chickens/index.txt +10 -0
  181. data/spec/data/site/content/tumblog/200807/the-wisdom-of-the-dutch/index.txt +11 -0
  182. data/spec/data/site/content/tumblog/200807/up-a-tree/index.txt +13 -0
  183. data/spec/data/site/content/tumblog/index.txt +37 -0
  184. data/spec/data/site/content/tumblog/rss.txt +37 -0
  185. data/spec/data/site/layouts/default.txt +58 -0
  186. data/spec/data/site/layouts/tumblog/default.txt +44 -0
  187. data/spec/data/site/layouts/tumblog/post.txt +15 -0
  188. data/spec/data/site/lib/breadcrumbs.rb +28 -0
  189. data/spec/data/site/lib/tumblog_helper.rb +32 -0
  190. data/spec/data/site/tasks/tumblog.rake +30 -0
  191. data/spec/data/site/templates/_partial.erb +10 -0
  192. data/spec/data/site/templates/atom_feed.erb +40 -0
  193. data/spec/data/site/templates/page.erb +18 -0
  194. data/spec/data/site/templates/presentation.erb +40 -0
  195. data/spec/data/site/templates/tumblog/conversation.erb +12 -0
  196. data/spec/data/site/templates/tumblog/link.erb +10 -0
  197. data/spec/data/site/templates/tumblog/photo.erb +13 -0
  198. data/spec/data/site/templates/tumblog/post.erb +12 -0
  199. data/spec/data/site/templates/tumblog/quote.erb +11 -0
  200. data/spec/spec.opts +1 -0
  201. data/spec/spec_helper.rb +51 -0
  202. data/spec/webby/apps/generator_spec.rb +116 -0
  203. data/spec/webby/apps/main_spec.rb +88 -0
  204. data/spec/webby/filters/basepath_spec.rb +167 -0
  205. data/spec/webby/filters/outline_spec.rb +92 -0
  206. data/spec/webby/filters/textile_spec.rb +20 -0
  207. data/spec/webby/helpers/capture_helper_spec.rb +56 -0
  208. data/spec/webby/renderer_spec.rb +139 -0
  209. data/spec/webby/resources/db_spec.rb +250 -0
  210. data/spec/webby/resources/layout_spec.rb +83 -0
  211. data/spec/webby/resources/meta_file_spec.rb +171 -0
  212. data/spec/webby/resources/page_spec.rb +111 -0
  213. data/spec/webby/resources/partial_spec.rb +58 -0
  214. data/spec/webby/resources/resource_spec.rb +219 -0
  215. data/spec/webby/resources/static_spec.rb +49 -0
  216. data/spec/webby/resources_spec.rb +69 -0
  217. data/tasks/ann.rake +81 -0
  218. data/tasks/bones.rake +21 -0
  219. data/tasks/gem.rake +187 -0
  220. data/tasks/git.rake +41 -0
  221. data/tasks/manifest.rake +48 -0
  222. data/tasks/notes.rake +28 -0
  223. data/tasks/post_load.rake +39 -0
  224. data/tasks/rdoc.rake +51 -0
  225. data/tasks/rubyforge.rake +55 -0
  226. data/tasks/setup.rb +268 -0
  227. data/tasks/spec.rake +55 -0
  228. data/tasks/website.rake +38 -0
  229. metadata +365 -0
@@ -0,0 +1,255 @@
1
+ require 'optparse'
2
+ require 'rake'
3
+
4
+ module Webby::Apps
5
+
6
+ class Main
7
+
8
+ # Create a new instance of Main, and run the +webby+ application given the
9
+ # command line _args_.
10
+ #
11
+ def self.run( args )
12
+ self.new.run args
13
+ end
14
+
15
+ attr_reader :cmd_line_options
16
+
17
+ # Create a new Main webby object for building websites.
18
+ #
19
+ def initialize
20
+ @stdout = $stdout
21
+ @cmd_line_options = {}
22
+ end
23
+
24
+ # Runs the main webby application. The command line arguments are passed
25
+ # in to this method as an array of strings. The command line arguments are
26
+ # parsed to figure out which rake task to invoke.
27
+ #
28
+ def run( args )
29
+ args = args.dup
30
+
31
+ parse args
32
+ init args
33
+ rake
34
+ end
35
+
36
+ # Parse the command line _args_ for options and commands to invoke.
37
+ #
38
+ def parse( args )
39
+ opts = OptionParser.new
40
+ opts.banner = 'Usage: webby [options] target [target args]'
41
+
42
+ opts.separator ''
43
+
44
+ desired_opts = %[--describe --prereqs --tasks --trace]
45
+ app.standard_rake_options.each do |options|
46
+ next unless desired_opts.include?(options.first)
47
+ opts.on(*options)
48
+ end
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
+
60
+ opts.separator ''
61
+ opts.separator 'common options:'
62
+
63
+ opts.on_tail( '-h', '--help', 'show this message' ) do
64
+ @stdout.puts opts
65
+ exit
66
+ end
67
+ opts.on_tail( '--version', 'show version' ) do
68
+ @stdout.puts "Webby #{::Webby::VERSION}"
69
+ exit
70
+ end
71
+
72
+ opts.parse! args
73
+
74
+ ARGV.replace Array(args.shift)
75
+ args.delete_if do |arg|
76
+ if %r/^[A-Z_]+=/ =~ arg
77
+ ARGV << arg
78
+ next true
79
+ end
80
+ false
81
+ end
82
+
83
+ args
84
+ end
85
+
86
+ # Initialize the Rake application object and load the core rake tasks, the
87
+ # site specific rake tasks, and the site specific ruby code. Any extra
88
+ # command line arguments are converted into a page name and directory that
89
+ # might get created (depending upon the task invoked).
90
+ #
91
+ def init( args )
92
+ # Make sure we're in a folder with a Sitefile
93
+ options = app.standard_rake_options
94
+ [['--rakefile', 'Sitefile'],
95
+ ['--no-search', nil],
96
+ ['--silent', nil]].each {|opt, value| options.assoc(opt).last.call(value)}
97
+
98
+ unless app.have_rakefile
99
+ raise RuntimeError, "Sitefile not found"
100
+ end
101
+
102
+ import_default_tasks
103
+ import_website_tasks
104
+ require_lib_files
105
+ capture_command_line_args(args)
106
+ args
107
+ end
108
+
109
+ # Execute the rake command.
110
+ #
111
+ def rake
112
+ app.init 'webby'
113
+ app.load_rakefile
114
+ load_command_line_options
115
+ app.top_level
116
+ end
117
+
118
+ # Return the Rake application object.
119
+ #
120
+ def app
121
+ Rake.application
122
+ end
123
+
124
+ # Returns the options hash from the Rake application object.
125
+ #
126
+ def options
127
+ app.options
128
+ end
129
+
130
+ # Search for the "Sitefile" starting in the current directory and working
131
+ # upwards through the filesystem until the root of the filesystem is
132
+ # reached. If a "Sitefile" is not found, a RuntimeError is raised.
133
+ #
134
+ def find_sitefile
135
+ here = Dir.pwd
136
+ while ! app.have_rakefile
137
+ Dir.chdir("..")
138
+ if Dir.pwd == here || options.nosearch
139
+ fail "No Sitefile found"
140
+ end
141
+ here = Dir.pwd
142
+ end
143
+ end
144
+
145
+ def import_default_tasks
146
+ Dir.glob(::Webby.libpath(%w[webby tasks *.rake])).sort.each {|fn| import fn}
147
+ end
148
+
149
+ def import_website_tasks
150
+ Dir.glob(::File.join(%w[tasks *.rake])).sort.each {|fn| import fn}
151
+ end
152
+
153
+ def require_lib_files
154
+ Dir.glob(::File.join(%w[lib ** *.rb])).sort.each {|fn| require fn}
155
+ end
156
+
157
+ def capture_command_line_args(args)
158
+ args = OpenStruct.new(:raw => args)
159
+
160
+ if args.raw.size > 1
161
+ ::Webby.deprecated "multiple arguments used for page title",
162
+ "please quote the page title"
163
+ end
164
+
165
+ dashed = args.raw.join('-').downcase
166
+ spaced = args.raw.join(' ')
167
+ dir = ::File.dirname(dashed)
168
+
169
+ args.dir = ('.' == dir ? '' : dir)
170
+ args.slug = ::Webby::Resources.basename(dashed).to_url
171
+ args.title = ::Webby::Resources.basename(spaced).titlecase
172
+
173
+ # page should be dir/slug without leading /
174
+ args.page = ::File.join(args.dir, args.slug).gsub(/^\//, '')
175
+
176
+ ext = ::File.extname(dashed)
177
+ args.page << ext unless ext.empty?
178
+
179
+ ::Webby.site.args = args
180
+ Object.const_set(:SITE, Webby.site)
181
+ args
182
+ end
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
+
192
+ end # class Main
193
+ end # module Webby::Apps
194
+
195
+ # :stopdoc:
196
+ # Monkey patches so that rake displays the correct application name in the
197
+ # help messages.
198
+ #
199
+ class Rake::Application
200
+ def display_prerequisites
201
+ tasks.each do |t|
202
+ puts "#{name} #{t.name}"
203
+ t.prerequisites.each { |pre| puts " #{pre}" }
204
+ end
205
+ end
206
+
207
+ def display_tasks_and_comments
208
+ displayable_tasks = tasks.select { |t|
209
+ t.comment && t.name =~ options.show_task_pattern
210
+ }
211
+ if options.full_description
212
+ displayable_tasks.each do |t|
213
+ puts "#{name} #{t.name_with_args}"
214
+ t.full_comment.split("\n").each do |line|
215
+ puts " #{line}"
216
+ end
217
+ puts
218
+ end
219
+ else
220
+ width = displayable_tasks.collect { |t| t.name_with_args.length }.max || 10
221
+ max_column = truncate_output? ? terminal_width - name.size - width - 7 : nil
222
+ displayable_tasks.each do |t|
223
+ printf "#{name} %-#{width}s # %s\n",
224
+ t.name_with_args, max_column ? truncate(t.comment, max_column) : t.comment
225
+ end
226
+ end
227
+ end
228
+
229
+ # Provide standard execption handling for the given block.
230
+ def standard_exception_handling
231
+ begin
232
+ yield
233
+ rescue SystemExit => ex
234
+ # Exit silently with current status
235
+ exit(ex.status)
236
+ rescue SystemExit, OptionParser::InvalidOption => ex
237
+ # Exit silently
238
+ exit(1)
239
+ rescue Exception => ex
240
+ # Exit with error message
241
+ $stderr.puts "#{name} aborted!"
242
+ $stderr.puts ex.message
243
+ if options.trace
244
+ $stderr.puts ex.backtrace.join("\n")
245
+ else
246
+ $stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
247
+ $stderr.puts "(See full trace by running task with --trace)"
248
+ end
249
+ exit(1)
250
+ end
251
+ end
252
+ end # class Rake::Application
253
+ # :startdoc:
254
+
255
+ # EOF
@@ -0,0 +1,157 @@
1
+ require 'directory_watcher'
2
+ require 'launchy'
3
+ require 'webrick'
4
+
5
+ module Webby
6
+
7
+ # The AutoBuilder class is used to monitor the content and layouts folders
8
+ # and to compile the resource files only when they are modified. If a
9
+ # layout is modified, then all resources that depend upon the layout are
10
+ # compiled.
11
+ #
12
+ class AutoBuilder
13
+
14
+ # TODO: hit Ctrl-C once to rebuild everything, and hit it twice to stop the autobuild loop
15
+
16
+ # call-seq:
17
+ # AutoBuilder.run
18
+ #
19
+ # Creates a new AutoBuilder and sets it running. This method will only
20
+ # return when the user presses Ctrl-C.
21
+ #
22
+ def self.run
23
+ self.new.run
24
+ end
25
+
26
+ attr_reader :logger
27
+
28
+ # call-seq:
29
+ # AutoBuilder.new
30
+ #
31
+ # Create a new AutoBuilder class.
32
+ #
33
+ def initialize
34
+ @logger = Logging::Logger[self]
35
+
36
+ @builder = Builder.new
37
+ @builder.load_files
38
+
39
+ @watcher = DirectoryWatcher.new '.', :interval => 2
40
+ @watcher.add_observer self
41
+
42
+ glob = []
43
+ glob << File.join(::Webby.site.layout_dir, '**', '*')
44
+ glob << File.join(::Webby.site.content_dir, '**', '*')
45
+ @watcher.glob = glob
46
+
47
+ @web_server = ::Webby.site.use_web_server ? WebServer.new : nil
48
+ end
49
+
50
+ # call-seq:
51
+ # update( *events )
52
+ #
53
+ # The update method is called by the DirectoryWatcher when files have been
54
+ # modified, added, or deleted. An array of events is passed to his method,
55
+ # and each event contains the event type and the path to the file.
56
+ #
57
+ def update( *events )
58
+ ary = events.find_all {|evt| evt.type != :removed}
59
+ return if ary.empty?
60
+
61
+ ary.each do |evt|
62
+ logger.debug "changed #{evt.path}"
63
+ next unless test ?f, evt.path
64
+ next if evt.path =~ ::Webby.exclude
65
+ Resources.new evt.path
66
+ end
67
+
68
+ logger.info 'running the build'
69
+ @builder.run :load_files => false, :verbose => false
70
+ rescue => err
71
+ logger.error err
72
+ end
73
+
74
+ # call-seq:
75
+ # run
76
+ #
77
+ # Starts the DirectoryWatcher running and waits till the user presses
78
+ # Ctrl-C to stop the watcher thread.
79
+ #
80
+ def run
81
+ logger.info 'starting autobuild (Ctrl-C to stop)'
82
+
83
+ Signal.trap('INT') {
84
+ @watcher.stop
85
+ @web_server.stop if @web_server
86
+ }
87
+
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
+
95
+ @watcher.join
96
+ @web_server.join if @web_server
97
+ end
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
+
154
+ end # class AutoBuilder
155
+ end # module Webby
156
+
157
+ # EOF
@@ -0,0 +1,180 @@
1
+ require 'find'
2
+ require 'fileutils'
3
+ require 'erb'
4
+
5
+ module Webby
6
+
7
+ # The Builder class performs the work of scanning the content folder,
8
+ # creating Resource objects, and converting / copying the contents to the
9
+ # output folder as needed.
10
+ #
11
+ class Builder
12
+
13
+ class << self
14
+
15
+ # call-seq:
16
+ # Builder.run( :rebuild => false )
17
+ #
18
+ # Create a new instance of the Builder class and invoke the run method.
19
+ # If the <code>:rebuild</code> option is given as +true+, then all pages
20
+ # will be recreated / copied.
21
+ #
22
+ def run( opts = {} )
23
+ self.new.run opts
24
+ end
25
+
26
+ # call-seq:
27
+ # Builder.create( page, :from => template, :locals => {} )
28
+ #
29
+ # This mehod is used to create a new _page_ in the content folder based
30
+ # on the specified template. _page_ is the relative path to the new page
31
+ # from the <code>content/</code> folder. The _template_ is the name of
32
+ # the template to use from the <code>templates/</code> folder.
33
+ #
34
+ def create( page, opts = {} )
35
+ tmpl = opts[:from]
36
+ raise Error, "template not given" unless tmpl
37
+
38
+ name = ::Webby::Resources.basename(page)
39
+ ext = ::Webby::Resources.extname(page)
40
+ dir = ::File.dirname(page)
41
+ dir = '' if dir == '.'
42
+
43
+ if tmpl.pathmap('%n') =~ %r/^_/
44
+ page = ::File.join(::Webby.site.content_dir, dir, '_'+name)
45
+ page << '.' << (ext.empty? ? 'txt' : ext)
46
+ elsif ::Webby.site.create_mode == 'directory' and name != 'index'
47
+ page = ::File.join(::Webby.site.content_dir, dir, name, 'index')
48
+ page << '.' << (ext.empty? ? 'txt' : ext)
49
+ else
50
+ page = ::File.join(::Webby.site.content_dir, page)
51
+ page << '.txt' if ext.empty?
52
+ end
53
+ raise Error, "#{page} already exists" if test ?e, page
54
+
55
+ Logging::Logger[self].info "creating #{page}"
56
+ FileUtils.mkdir_p ::File.dirname(page)
57
+
58
+ context = scope
59
+ opts[:locals].each do |k,v|
60
+ Thread.current[:value] = v
61
+ definition = "#{k} = Thread.current[:value]"
62
+ eval(definition, context)
63
+ end if opts.has_key?(:locals)
64
+
65
+ str = ERB.new(::File.read(tmpl), nil, '-').result(context)
66
+ ::File.open(page, 'w') {|fd| fd.write str}
67
+
68
+ page
69
+ end
70
+
71
+ # call-seq:
72
+ # Builder.new_page_info => [page, title, directory]
73
+ #
74
+ def new_page_info
75
+ args = Webby.site.args
76
+
77
+ if args.raw.empty?
78
+ task_name = Rake.application.top_level_tasks.first
79
+ raise "Usage: webby #{task_name} path"
80
+ end
81
+
82
+ [args.page, args.title, args.dir]
83
+ end
84
+
85
+ private
86
+
87
+ # Returns the binding in the scope of the Builder class object.
88
+ #
89
+ def scope() binding end
90
+
91
+ end # class << self
92
+
93
+ # call-seq:
94
+ # Builder.new
95
+ #
96
+ # Creates a new Builder object for creating pages from the content and
97
+ # layout directories.
98
+ #
99
+ def initialize
100
+ @logger = Logging::Logger[self]
101
+ end
102
+
103
+ # call-seq:
104
+ # run( :rebuild => false, :load_files => true )
105
+ #
106
+ # Runs the Webby builder by loading in the layout files from the
107
+ # <code>layouts/</code> folder and the content from the
108
+ # <code>contents/</code> folder. Content is analyzed, and those that need
109
+ # to be copied or compiled (filtered using ERB, Texttile, Markdown, etc.)
110
+ # are handled. The results are placed in the <code>output/</code> folder.
111
+ #
112
+ # If the <code>:rebuild</code> flag is set to +true+, then all content is
113
+ # copied and/or compiled to the output folder.
114
+ #
115
+ # A content file can mark itself as dirty by setting the +dirty+ flag to
116
+ # +true+ in the meta-data of the file. This will cause the contenet to
117
+ # always be compiled when the builder is run. Conversely, setting the
118
+ # dirty flag to +false+ will cause the content to never be compiled or
119
+ # copied to the output folder.
120
+ #
121
+ # A content file needs to be built if the age of the file is less then the
122
+ # age of the output product -- i.e. the content file has been modified
123
+ # more recently than the output file.
124
+ #
125
+ def run( opts = {} )
126
+ opts[:load_files] = true unless opts.has_key?(:load_files)
127
+ verbose = opts.getopt(:verbose, true)
128
+
129
+ unless test(?d, output_dir)
130
+ journal.create output_dir
131
+ FileUtils.mkdir output_dir
132
+ end
133
+
134
+ load_files if opts[:load_files]
135
+
136
+ Resources.pages.each do |page|
137
+ unless page.dirty? or opts[:rebuild]
138
+ journal.identical(page.destination) if verbose
139
+ next
140
+ end
141
+
142
+ # copy the resource to the output directory if it is static
143
+ if page.instance_of? Resources::Static
144
+ FileUtils.mkdir_p ::File.dirname(page.destination)
145
+ journal.create_or_update(page)
146
+ FileUtils.cp page.path, page.destination
147
+ FileUtils.chmod 0644, page.destination
148
+
149
+ # otherwise, layout the resource and write the results to
150
+ # the output directory
151
+ else Renderer.write(page) end
152
+ end
153
+
154
+ # touch the cairn so we know when the website was last generated
155
+ FileUtils.touch ::Webby.cairn
156
+
157
+ nil
158
+ end
159
+
160
+ # Scan the <code>layouts/</code> folder and the <code>content/</code>
161
+ # folder and create a new Resource object for each file found there.
162
+ #
163
+ def load_files
164
+ ::Find.find(layout_dir, content_dir) do |path|
165
+ next unless test ?f, path
166
+ next if path =~ ::Webby.exclude
167
+ Resources.new path
168
+ end
169
+ end
170
+
171
+ %w(output_dir layout_dir content_dir).each do |key|
172
+ self.class_eval <<-CODE
173
+ def #{key}( ) ::Webby.site.#{key} end
174
+ CODE
175
+ end
176
+
177
+ end # class Builder
178
+ end # module Webby
179
+
180
+ # EOF