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.
- data/History.txt +206 -0
- data/Manifest.txt +228 -0
- data/README.txt +92 -0
- data/Rakefile +49 -0
- data/bin/webby +41 -0
- data/bin/webby-gen +41 -0
- data/examples/blog/Sitefile +7 -0
- data/examples/blog/tasks/blog.rake +72 -0
- data/examples/blog/templates/atom_feed.erb +40 -0
- data/examples/blog/templates/blog/month.erb +22 -0
- data/examples/blog/templates/blog/post.erb +16 -0
- data/examples/blog/templates/blog/year.erb +22 -0
- data/examples/presentation/Sitefile +10 -0
- data/examples/presentation/content/css/uv/twilight.css +137 -0
- data/examples/presentation/content/presentation/_sample_code.txt +10 -0
- data/examples/presentation/content/presentation/index.txt +63 -0
- data/examples/presentation/content/presentation/s5/blank.gif +0 -0
- data/examples/presentation/content/presentation/s5/bodybg.gif +0 -0
- data/examples/presentation/content/presentation/s5/framing.css +23 -0
- data/examples/presentation/content/presentation/s5/iepngfix.htc +42 -0
- data/examples/presentation/content/presentation/s5/opera.css +7 -0
- data/examples/presentation/content/presentation/s5/outline.css +15 -0
- data/examples/presentation/content/presentation/s5/pretty.css +86 -0
- data/examples/presentation/content/presentation/s5/print.css +25 -0
- data/examples/presentation/content/presentation/s5/s5-core.css +9 -0
- data/examples/presentation/content/presentation/s5/slides.css +3 -0
- data/examples/presentation/content/presentation/s5/slides.js +553 -0
- data/examples/presentation/layouts/presentation.txt +43 -0
- data/examples/presentation/templates/_code_partial.erb +13 -0
- data/examples/presentation/templates/presentation.erb +40 -0
- data/examples/tumblog/Sitefile +9 -0
- data/examples/tumblog/content/css/tumblog.css +308 -0
- data/examples/tumblog/content/images/tumblog/permalink.gif +0 -0
- data/examples/tumblog/content/images/tumblog/rss.gif +0 -0
- data/examples/tumblog/content/tumblog/200806/the-noble-chicken/index.txt +12 -0
- data/examples/tumblog/content/tumblog/200807/historical-perspectives-on-the-classic-chicken-joke/index.txt +12 -0
- data/examples/tumblog/content/tumblog/200807/mad-city-chickens/index.txt +10 -0
- data/examples/tumblog/content/tumblog/200807/the-wisdom-of-the-dutch/index.txt +11 -0
- data/examples/tumblog/content/tumblog/200807/up-a-tree/index.txt +13 -0
- data/examples/tumblog/content/tumblog/index.txt +37 -0
- data/examples/tumblog/content/tumblog/rss.txt +37 -0
- data/examples/tumblog/layouts/tumblog/default.txt +44 -0
- data/examples/tumblog/layouts/tumblog/post.txt +15 -0
- data/examples/tumblog/lib/tumblog_helper.rb +32 -0
- data/examples/tumblog/tasks/tumblog.rake +30 -0
- data/examples/tumblog/templates/atom_feed.erb +40 -0
- data/examples/tumblog/templates/tumblog/conversation.erb +12 -0
- data/examples/tumblog/templates/tumblog/link.erb +10 -0
- data/examples/tumblog/templates/tumblog/photo.erb +13 -0
- data/examples/tumblog/templates/tumblog/post.erb +12 -0
- data/examples/tumblog/templates/tumblog/quote.erb +11 -0
- data/examples/webby/Sitefile +19 -0
- data/examples/webby/content/communicate/index.txt +28 -0
- data/examples/webby/content/css/background.gif +0 -0
- data/examples/webby/content/css/blueprint/print.css +76 -0
- data/examples/webby/content/css/blueprint/screen.css +696 -0
- data/examples/webby/content/css/coderay.css +96 -0
- data/examples/webby/content/css/site.css +196 -0
- data/examples/webby/content/css/uv/twilight.css +137 -0
- data/examples/webby/content/index.txt +37 -0
- data/examples/webby/content/learn/index.txt +28 -0
- data/examples/webby/content/reference/index.txt +204 -0
- data/examples/webby/content/release-notes/index.txt +21 -0
- data/examples/webby/content/release-notes/rel-0-9-0/index.txt +74 -0
- data/examples/webby/content/release-notes/rel-0-9-1/index.txt +93 -0
- data/examples/webby/content/release-notes/rel-0-9-2/index.txt +14 -0
- data/examples/webby/content/release-notes/rel-0-9-3/index.txt +49 -0
- data/examples/webby/content/robots.txt +6 -0
- data/examples/webby/content/script/jquery.corner.js +152 -0
- data/examples/webby/content/script/jquery.js +31 -0
- data/examples/webby/content/sitemap.txt +31 -0
- data/examples/webby/content/tips_and_tricks/index.txt +97 -0
- data/examples/webby/content/tutorial/index.txt +135 -0
- data/examples/webby/content/user-manual/index.txt +419 -0
- data/examples/webby/layouts/default.txt +49 -0
- data/examples/webby/templates/page.erb +10 -0
- data/examples/website/Sitefile +7 -0
- data/examples/website/content/css/blueprint/License.txt +21 -0
- data/examples/website/content/css/blueprint/Readme.txt +100 -0
- data/examples/website/content/css/blueprint/compressed/print.css +76 -0
- data/examples/website/content/css/blueprint/compressed/screen.css +696 -0
- data/examples/website/content/css/blueprint/lib/forms.css +45 -0
- data/examples/website/content/css/blueprint/lib/grid.css +193 -0
- data/examples/website/content/css/blueprint/lib/grid.png +0 -0
- data/examples/website/content/css/blueprint/lib/ie.css +30 -0
- data/examples/website/content/css/blueprint/lib/reset.css +39 -0
- data/examples/website/content/css/blueprint/lib/typography.css +116 -0
- data/examples/website/content/css/blueprint/plugins/buttons/Readme +31 -0
- data/examples/website/content/css/blueprint/plugins/buttons/buttons.css +97 -0
- data/examples/website/content/css/blueprint/plugins/buttons/icons/cross.png +0 -0
- data/examples/website/content/css/blueprint/plugins/buttons/icons/key.png +0 -0
- data/examples/website/content/css/blueprint/plugins/buttons/icons/tick.png +0 -0
- data/examples/website/content/css/blueprint/plugins/css-classes/Readme +14 -0
- data/examples/website/content/css/blueprint/plugins/css-classes/css-classes.css +24 -0
- data/examples/website/content/css/blueprint/plugins/fancy-type/Readme +22 -0
- data/examples/website/content/css/blueprint/plugins/fancy-type/fancy-type-compressed.css +5 -0
- data/examples/website/content/css/blueprint/plugins/fancy-type/fancy-type.css +74 -0
- data/examples/website/content/css/blueprint/print.css +68 -0
- data/examples/website/content/css/blueprint/screen.css +22 -0
- data/examples/website/content/css/coderay.css +111 -0
- data/examples/website/content/css/site.css +67 -0
- data/examples/website/content/index.txt +19 -0
- data/examples/website/layouts/default.txt +58 -0
- data/examples/website/lib/breadcrumbs.rb +28 -0
- data/examples/website/templates/_partial.erb +10 -0
- data/examples/website/templates/page.erb +18 -0
- data/lib/webby.rb +221 -0
- data/lib/webby/apps.rb +12 -0
- data/lib/webby/apps/generator.rb +276 -0
- data/lib/webby/apps/main.rb +255 -0
- data/lib/webby/auto_builder.rb +157 -0
- data/lib/webby/builder.rb +180 -0
- data/lib/webby/core_ext/enumerable.rb +11 -0
- data/lib/webby/core_ext/hash.rb +28 -0
- data/lib/webby/core_ext/kernel.rb +26 -0
- data/lib/webby/core_ext/string.rb +163 -0
- data/lib/webby/core_ext/time.rb +9 -0
- data/lib/webby/filters.rb +83 -0
- data/lib/webby/filters/basepath.rb +97 -0
- data/lib/webby/filters/erb.rb +9 -0
- data/lib/webby/filters/haml.rb +18 -0
- data/lib/webby/filters/markdown.rb +16 -0
- data/lib/webby/filters/outline.rb +309 -0
- data/lib/webby/filters/sass.rb +17 -0
- data/lib/webby/filters/slides.rb +56 -0
- data/lib/webby/filters/textile.rb +16 -0
- data/lib/webby/filters/tidy.rb +76 -0
- data/lib/webby/filters/wiki_words.rb +14 -0
- data/lib/webby/helpers.rb +30 -0
- data/lib/webby/helpers/capture_helper.rb +141 -0
- data/lib/webby/helpers/coderay_helper.rb +69 -0
- data/lib/webby/helpers/graphviz_helper.rb +136 -0
- data/lib/webby/helpers/tag_helper.rb +65 -0
- data/lib/webby/helpers/tex_img_helper.rb +133 -0
- data/lib/webby/helpers/ultraviolet_helper.rb +63 -0
- data/lib/webby/helpers/url_helper.rb +241 -0
- data/lib/webby/journal.rb +126 -0
- data/lib/webby/link_validator.rb +152 -0
- data/lib/webby/renderer.rb +386 -0
- data/lib/webby/resources.rb +136 -0
- data/lib/webby/resources/db.rb +251 -0
- data/lib/webby/resources/layout.rb +54 -0
- data/lib/webby/resources/meta_file.rb +211 -0
- data/lib/webby/resources/page.rb +81 -0
- data/lib/webby/resources/partial.rb +85 -0
- data/lib/webby/resources/resource.rb +201 -0
- data/lib/webby/resources/static.rb +36 -0
- data/lib/webby/stelan/mktemp.rb +135 -0
- data/lib/webby/stelan/paginator.rb +165 -0
- data/lib/webby/stelan/spawner.rb +339 -0
- data/lib/webby/tasks/build.rake +27 -0
- data/lib/webby/tasks/create.rake +22 -0
- data/lib/webby/tasks/deploy.rake +22 -0
- data/lib/webby/tasks/growl.rake +16 -0
- data/lib/webby/tasks/validate.rake +19 -0
- data/spec/core_ext/hash_spec.rb +47 -0
- data/spec/core_ext/string_spec.rb +110 -0
- data/spec/core_ext/time_spec.rb +19 -0
- data/spec/data/hooligans/bad_meta_data_1.txt +34 -0
- data/spec/data/hooligans/bad_meta_data_2.txt +34 -0
- data/spec/data/outline/basic.out +81 -0
- data/spec/data/outline/basic.txt +25 -0
- data/spec/data/outline/no_clobber.out +86 -0
- data/spec/data/outline/numbering.out +81 -0
- data/spec/data/outline/numbering_only.out +21 -0
- data/spec/data/outline/toc_range_1.out +66 -0
- data/spec/data/outline/toc_range_2.out +55 -0
- data/spec/data/outline/toc_style.out +81 -0
- data/spec/data/site/Sitefile +9 -0
- data/spec/data/site/content/_partial.txt +10 -0
- data/spec/data/site/content/css/coderay.css +111 -0
- data/spec/data/site/content/css/site.css +67 -0
- data/spec/data/site/content/css/tumblog.css +308 -0
- data/spec/data/site/content/images/tumblog/permalink.gif +0 -0
- data/spec/data/site/content/images/tumblog/rss.gif +0 -0
- data/spec/data/site/content/index.txt +19 -0
- data/spec/data/site/content/photos.txt +21 -0
- data/spec/data/site/content/tumblog/200806/the-noble-chicken/index.txt +12 -0
- data/spec/data/site/content/tumblog/200807/historical-perspectives-on-the-classic-chicken-joke/index.txt +12 -0
- data/spec/data/site/content/tumblog/200807/mad-city-chickens/index.txt +10 -0
- data/spec/data/site/content/tumblog/200807/the-wisdom-of-the-dutch/index.txt +11 -0
- data/spec/data/site/content/tumblog/200807/up-a-tree/index.txt +13 -0
- data/spec/data/site/content/tumblog/index.txt +37 -0
- data/spec/data/site/content/tumblog/rss.txt +37 -0
- data/spec/data/site/layouts/default.txt +58 -0
- data/spec/data/site/layouts/tumblog/default.txt +44 -0
- data/spec/data/site/layouts/tumblog/post.txt +15 -0
- data/spec/data/site/lib/breadcrumbs.rb +28 -0
- data/spec/data/site/lib/tumblog_helper.rb +32 -0
- data/spec/data/site/tasks/tumblog.rake +30 -0
- data/spec/data/site/templates/_partial.erb +10 -0
- data/spec/data/site/templates/atom_feed.erb +40 -0
- data/spec/data/site/templates/page.erb +18 -0
- data/spec/data/site/templates/presentation.erb +40 -0
- data/spec/data/site/templates/tumblog/conversation.erb +12 -0
- data/spec/data/site/templates/tumblog/link.erb +10 -0
- data/spec/data/site/templates/tumblog/photo.erb +13 -0
- data/spec/data/site/templates/tumblog/post.erb +12 -0
- data/spec/data/site/templates/tumblog/quote.erb +11 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/webby/apps/generator_spec.rb +116 -0
- data/spec/webby/apps/main_spec.rb +88 -0
- data/spec/webby/filters/basepath_spec.rb +167 -0
- data/spec/webby/filters/outline_spec.rb +92 -0
- data/spec/webby/filters/textile_spec.rb +20 -0
- data/spec/webby/helpers/capture_helper_spec.rb +56 -0
- data/spec/webby/renderer_spec.rb +139 -0
- data/spec/webby/resources/db_spec.rb +250 -0
- data/spec/webby/resources/layout_spec.rb +83 -0
- data/spec/webby/resources/meta_file_spec.rb +171 -0
- data/spec/webby/resources/page_spec.rb +111 -0
- data/spec/webby/resources/partial_spec.rb +58 -0
- data/spec/webby/resources/resource_spec.rb +219 -0
- data/spec/webby/resources/static_spec.rb +49 -0
- data/spec/webby/resources_spec.rb +69 -0
- data/tasks/ann.rake +81 -0
- data/tasks/bones.rake +21 -0
- data/tasks/gem.rake +187 -0
- data/tasks/git.rake +41 -0
- data/tasks/manifest.rake +48 -0
- data/tasks/notes.rake +28 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +268 -0
- data/tasks/spec.rake +55 -0
- data/tasks/website.rake +38 -0
- 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
|