francois-webby 0.9.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +218 -0
- data/README.rdoc +92 -0
- data/Rakefile +62 -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 +47 -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/ie.css +26 -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/buttons/readme.txt +32 -0
- data/examples/website/content/css/blueprint/plugins/buttons/screen.css +97 -0
- data/examples/website/content/css/blueprint/plugins/fancy-type/readme.txt +14 -0
- data/examples/website/content/css/blueprint/plugins/fancy-type/screen.css +71 -0
- data/examples/website/content/css/blueprint/plugins/link-icons/icons/doc.png +0 -0
- data/examples/website/content/css/blueprint/plugins/link-icons/icons/email.png +0 -0
- data/examples/website/content/css/blueprint/plugins/link-icons/icons/external.png +0 -0
- data/examples/website/content/css/blueprint/plugins/link-icons/icons/feed.png +0 -0
- data/examples/website/content/css/blueprint/plugins/link-icons/icons/im.png +0 -0
- data/examples/website/content/css/blueprint/plugins/link-icons/icons/pdf.png +0 -0
- data/examples/website/content/css/blueprint/plugins/link-icons/icons/visited.png +0 -0
- data/examples/website/content/css/blueprint/plugins/link-icons/icons/xls.png +0 -0
- data/examples/website/content/css/blueprint/plugins/link-icons/readme.txt +18 -0
- data/examples/website/content/css/blueprint/plugins/link-icons/screen.css +40 -0
- data/examples/website/content/css/blueprint/plugins/rtl/readme.txt +10 -0
- data/examples/website/content/css/blueprint/plugins/rtl/screen.css +109 -0
- data/examples/website/content/css/blueprint/print.css +30 -0
- data/examples/website/content/css/blueprint/screen.css +251 -0
- data/examples/website/content/css/blueprint/src/forms.css +49 -0
- data/examples/website/content/css/blueprint/src/grid.css +212 -0
- data/examples/website/content/css/blueprint/src/grid.png +0 -0
- data/examples/website/content/css/blueprint/src/ie.css +59 -0
- data/examples/website/content/css/blueprint/src/print.css +85 -0
- data/examples/website/content/css/blueprint/src/reset.css +38 -0
- data/examples/website/content/css/blueprint/src/typography.css +105 -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 +61 -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/apps/generator.rb +276 -0
- data/lib/webby/apps/main.rb +258 -0
- data/lib/webby/apps.rb +12 -0
- data/lib/webby/auto_builder.rb +157 -0
- data/lib/webby/builder.rb +172 -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/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/maruku.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/filters.rb +85 -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/helpers.rb +30 -0
- data/lib/webby/journal.rb +126 -0
- data/lib/webby/link_validator.rb +160 -0
- data/lib/webby/renderer.rb +389 -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/resources.rb +137 -0
- data/lib/webby/stelan/mktemp.rb +135 -0
- data/lib/webby/stelan/paginator.rb +165 -0
- data/lib/webby/tasks/build.rake +27 -0
- data/lib/webby/tasks/create.rake +25 -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/lib/webby.rb +232 -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/html/anchor.html +11 -0
- data/spec/data/html/external.html +10 -0
- data/spec/data/html/invalid-relative.html +10 -0
- data/spec/data/html/relative-anchor.html +10 -0
- data/spec/data/html/relative-invalid-anchor.html +10 -0
- data/spec/data/html/relative.html +10 -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 +58 -0
- data/spec/webby/apps/generator_spec.rb +117 -0
- data/spec/webby/apps/main_spec.rb +88 -0
- data/spec/webby/filters/basepath_spec.rb +167 -0
- data/spec/webby/filters/maruku_spec.rb +31 -0
- data/spec/webby/filters/outline_spec.rb +92 -0
- data/spec/webby/filters/textile_spec.rb +31 -0
- data/spec/webby/helpers/capture_helper_spec.rb +56 -0
- data/spec/webby/link_validator_spec.rb +154 -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/mswin32.rake +38 -0
- data/tasks/website.rake +37 -0
- metadata +372 -0
data/lib/webby/apps.rb
ADDED
@@ -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
|
+
::Webby.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.web_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.web_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,172 @@
|
|
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
|
+
# TODO: maybe even get rid of this method altogether
|
78
|
+
raise "Usage: webby #{args.rake.first} 'path'" if args.raw.empty?
|
79
|
+
|
80
|
+
[args.page, args.title, args.dir]
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# Returns the binding in the scope of the Builder class object.
|
86
|
+
#
|
87
|
+
def scope() binding end
|
88
|
+
|
89
|
+
end # class << self
|
90
|
+
|
91
|
+
# call-seq:
|
92
|
+
# Builder.new
|
93
|
+
#
|
94
|
+
# Creates a new Builder object for creating pages from the content and
|
95
|
+
# layout directories.
|
96
|
+
#
|
97
|
+
def initialize
|
98
|
+
@logger = Logging::Logger[self]
|
99
|
+
end
|
100
|
+
|
101
|
+
# call-seq:
|
102
|
+
# run( :rebuild => false, :load_files => true )
|
103
|
+
#
|
104
|
+
# Runs the Webby builder by loading in the layout files from the
|
105
|
+
# <code>layouts/</code> folder and the content from the
|
106
|
+
# <code>contents/</code> folder. Content is analyzed, and those that need
|
107
|
+
# to be copied or compiled (filtered using ERB, Texttile, Markdown, etc.)
|
108
|
+
# are handled. The results are placed in the <code>output/</code> folder.
|
109
|
+
#
|
110
|
+
# If the <code>:rebuild</code> flag is set to +true+, then all content is
|
111
|
+
# copied and/or compiled to the output folder.
|
112
|
+
#
|
113
|
+
# A content file can mark itself as dirty by setting the +dirty+ flag to
|
114
|
+
# +true+ in the meta-data of the file. This will cause the contenet to
|
115
|
+
# always be compiled when the builder is run. Conversely, setting the
|
116
|
+
# dirty flag to +false+ will cause the content to never be compiled or
|
117
|
+
# copied to the output folder.
|
118
|
+
#
|
119
|
+
# A content file needs to be built if the age of the file is less then the
|
120
|
+
# age of the output product -- i.e. the content file has been modified
|
121
|
+
# more recently than the output file.
|
122
|
+
#
|
123
|
+
def run( opts = {} )
|
124
|
+
opts[:load_files] = true unless opts.has_key?(:load_files)
|
125
|
+
verbose = opts.getopt(:verbose, true)
|
126
|
+
|
127
|
+
unless test(?d, output_dir)
|
128
|
+
journal.create output_dir
|
129
|
+
FileUtils.mkdir output_dir
|
130
|
+
end
|
131
|
+
|
132
|
+
::Webby.load_files if opts[:load_files]
|
133
|
+
|
134
|
+
Resources.pages.each do |page|
|
135
|
+
unless page.dirty? or opts[:rebuild]
|
136
|
+
journal.identical(page.destination) if verbose
|
137
|
+
next
|
138
|
+
end
|
139
|
+
|
140
|
+
# copy the resource to the output directory if it is static
|
141
|
+
if page.instance_of? Resources::Static
|
142
|
+
FileUtils.mkdir_p ::File.dirname(page.destination)
|
143
|
+
journal.create_or_update(page)
|
144
|
+
FileUtils.cp page.path, page.destination
|
145
|
+
FileUtils.chmod 0644, page.destination
|
146
|
+
|
147
|
+
# otherwise, layout the resource and write the results to
|
148
|
+
# the output directory
|
149
|
+
else Renderer.write(page) end
|
150
|
+
end
|
151
|
+
|
152
|
+
# touch the cairn so we know when the website was last generated
|
153
|
+
FileUtils.touch ::Webby.cairn
|
154
|
+
|
155
|
+
nil
|
156
|
+
end
|
157
|
+
|
158
|
+
def load_files
|
159
|
+
::Webby.deprecated "load_files", "it is being replaced by the Webby#load() method"
|
160
|
+
::Webby.load_files
|
161
|
+
end
|
162
|
+
|
163
|
+
%w(output_dir layout_dir content_dir).each do |key|
|
164
|
+
self.class_eval <<-CODE
|
165
|
+
def #{key}( ) ::Webby.site.#{key} end
|
166
|
+
CODE
|
167
|
+
end
|
168
|
+
|
169
|
+
end # class Builder
|
170
|
+
end # module Webby
|
171
|
+
|
172
|
+
# EOF
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
class Hash
|
3
|
+
|
4
|
+
def sanitize!
|
5
|
+
h = self.injecting({}) do |h, (k, v)|
|
6
|
+
h[k] = case v
|
7
|
+
when 'none', 'nil'; nil
|
8
|
+
when 'true', 'yes'; true
|
9
|
+
when 'false', 'no'; false
|
10
|
+
else v end
|
11
|
+
end
|
12
|
+
self.replace h
|
13
|
+
end
|
14
|
+
|
15
|
+
def stringify_keys
|
16
|
+
h = {}
|
17
|
+
self.each {|k,v| h[k.to_s] = v}
|
18
|
+
return h
|
19
|
+
end
|
20
|
+
|
21
|
+
def symbolize_keys
|
22
|
+
h = {}
|
23
|
+
self.each {|k,v| h[k.to_sym] = v}
|
24
|
+
return h
|
25
|
+
end
|
26
|
+
end # class Hash
|
27
|
+
|
28
|
+
# EOF
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
module Kernel
|
3
|
+
|
4
|
+
# :stopdoc:
|
5
|
+
WINDOWS = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM
|
6
|
+
DEV_NULL = WINDOWS ? 'NUL:' : '/dev/null'
|
7
|
+
# :startdoc:
|
8
|
+
|
9
|
+
def cmd_available?( *args )
|
10
|
+
io = [STDOUT.dup, STDERR.dup]
|
11
|
+
STDOUT.reopen DEV_NULL
|
12
|
+
STDERR.reopen DEV_NULL
|
13
|
+
system(*(args.flatten))
|
14
|
+
ensure
|
15
|
+
STDOUT.reopen io.first
|
16
|
+
STDERR.reopen io.last
|
17
|
+
$stdout, $stderr = STDOUT, STDERR
|
18
|
+
end
|
19
|
+
|
20
|
+
def journal
|
21
|
+
@journal ||= ::Webby::Journal.new
|
22
|
+
end
|
23
|
+
|
24
|
+
end # module Kernel
|
25
|
+
|
26
|
+
# EOF
|
@@ -0,0 +1,163 @@
|
|
1
|
+
|
2
|
+
class String
|
3
|
+
|
4
|
+
def self.small_words
|
5
|
+
@small_words ||= %w(a an and as at but by en for if in of on or the to v[.]? via vs[.]?)
|
6
|
+
end
|
7
|
+
|
8
|
+
def /( path )
|
9
|
+
::File.join(self, path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def titlecase
|
13
|
+
swrgxp = self.class.small_words.join('|')
|
14
|
+
|
15
|
+
parts = self.split( %r/( [:.;?!][ ] | (?:[ ]|^)["“] )/x )
|
16
|
+
parts.each do |part|
|
17
|
+
part.gsub!(%r/\b[[:alpha:]][[:lower:].'’]*\b/) do |s|
|
18
|
+
s =~ %r/\w+\.\w+/ ? s : s.capitalize
|
19
|
+
end
|
20
|
+
|
21
|
+
# Lowercase the small words
|
22
|
+
part.gsub!(%r/\b(#{swrgxp})\b/i) {|w| w.downcase}
|
23
|
+
|
24
|
+
# If the first word is a small word, then capitalize it
|
25
|
+
part.gsub!(%r/\A([[:punct:]]*)(#{swrgxp})\b/) {$1 + $2.capitalize}
|
26
|
+
|
27
|
+
# If the last word is a small word, then capitalize it
|
28
|
+
part.gsub!(%r/\b(#{swrgxp})([^\w\s]*)\z/) {$1.capitalize + $2}
|
29
|
+
end
|
30
|
+
|
31
|
+
str = parts.join
|
32
|
+
|
33
|
+
# Special cases:
|
34
|
+
str.gsub!(/ V(s?)\. /, ' v\1. ') # "v." and "vs."
|
35
|
+
str.gsub!(/(['’])S\b/, '\1s') # 'S (otherwise you get "the SEC'S decision")
|
36
|
+
str.gsub!(/\b(AT&T|Q&A)\b/i) { |w| w.upcase } # "AT&T" and "Q&A", which get tripped up.
|
37
|
+
|
38
|
+
str
|
39
|
+
end
|
40
|
+
|
41
|
+
# Borrowed from the excellent StringEx library: git://github.com/rsl/stringex.git
|
42
|
+
|
43
|
+
# Create a URI-friendly representation of the string.
|
44
|
+
def to_url
|
45
|
+
remove_formatting.downcase.replace_whitespace("-").collapse("-")
|
46
|
+
end
|
47
|
+
|
48
|
+
# Performs multiple text manipulations. Essentially a shortcut for typing them all. View source
|
49
|
+
# below to see which methods are run.
|
50
|
+
def remove_formatting
|
51
|
+
strip_html_tags.convert_accented_entities.convert_misc_entities.convert_misc_characters.collapse
|
52
|
+
end
|
53
|
+
|
54
|
+
# Removes HTML tags from text. This code is simplified from Tobias Luettke's regular expression
|
55
|
+
# in Typo[http://typosphere.org].
|
56
|
+
def strip_html_tags(leave_whitespace = false)
|
57
|
+
name = /[\w:_-]+/
|
58
|
+
value = /([A-Za-z0-9]+|('[^']*?'|"[^"]*?"))/
|
59
|
+
attr = /(#{name}(\s*=\s*#{value})?)/
|
60
|
+
rx = /<[!\/?\[]?(#{name}|--)(\s+(#{attr}(\s+#{attr})*))?\s*([!\/?\]]+|--)?>/
|
61
|
+
(leave_whitespace) ? gsub(rx, "").strip : gsub(rx, "").gsub(/\s+/, " ").strip
|
62
|
+
end
|
63
|
+
|
64
|
+
# Converts HTML entities into the respective non-accented letters. Examples:
|
65
|
+
#
|
66
|
+
# "á".convert_accented_entities # => "a"
|
67
|
+
# "ç".convert_accented_entities # => "c"
|
68
|
+
# "è".convert_accented_entities # => "e"
|
69
|
+
# "î".convert_accented_entities # => "i"
|
70
|
+
# "ø".convert_accented_entities # => "o"
|
71
|
+
# "ü".convert_accented_entities # => "u"
|
72
|
+
#
|
73
|
+
# Note: This does not do any conversion of Unicode/Ascii accented-characters. For that
|
74
|
+
# functionality please use <tt>to_ascii</tt>.
|
75
|
+
def convert_accented_entities
|
76
|
+
gsub(/&([A-Za-z])(grave|acute|circ|tilde|uml|ring|cedil|slash);/, '\1')
|
77
|
+
end
|
78
|
+
|
79
|
+
# Converts HTML entities (taken from common Textile/RedCloth formattings) into plain text formats.
|
80
|
+
#
|
81
|
+
# Note: This isn't an attempt at complete conversion of HTML entities, just those most likely
|
82
|
+
# to be generated by Textile.
|
83
|
+
def convert_misc_entities
|
84
|
+
dummy = dup
|
85
|
+
{
|
86
|
+
"#822[01]" => "\"",
|
87
|
+
"#821[67]" => "'",
|
88
|
+
"#8230" => "...",
|
89
|
+
"#8211" => "-",
|
90
|
+
"#8212" => "--",
|
91
|
+
"#215" => "x",
|
92
|
+
"gt" => ">",
|
93
|
+
"lt" => "<",
|
94
|
+
"(#8482|trade)" => "(tm)",
|
95
|
+
"(#174|reg)" => "(r)",
|
96
|
+
"(#169|copy)" => "(c)",
|
97
|
+
"(#38|amp)" => "and",
|
98
|
+
"nbsp" => " ",
|
99
|
+
"(#162|cent)" => " cent",
|
100
|
+
"(#163|pound)" => " pound",
|
101
|
+
"(#188|frac14)" => "one fourth",
|
102
|
+
"(#189|frac12)" => "half",
|
103
|
+
"(#190|frac34)" => "three fourths",
|
104
|
+
"(#176|deg)" => " degrees"
|
105
|
+
}.each do |textiled, normal|
|
106
|
+
dummy.gsub!(/&#{textiled};/, normal)
|
107
|
+
end
|
108
|
+
dummy.gsub(/&[^;]+;/, "")
|
109
|
+
end
|
110
|
+
|
111
|
+
# Converts various common plaintext characters to a more URI-friendly representation.
|
112
|
+
# Examples:
|
113
|
+
#
|
114
|
+
# "foo & bar".convert_misc_characters # => "foo and bar"
|
115
|
+
# "Chanel #9".convert_misc_characters # => "Chanel number nine"
|
116
|
+
# "user@host".convert_misc_characters # => "user at host"
|
117
|
+
# "google.com".convert_misc_characters # => "google dot com"
|
118
|
+
# "$10".convert_misc_characters # => "10 dollars"
|
119
|
+
# "*69".convert_misc_characters # => "star 69"
|
120
|
+
# "100%".convert_misc_characters # => "100 percent"
|
121
|
+
# "windows/mac/linux".convert_misc_characters # => "windows slash mac slash linux"
|
122
|
+
#
|
123
|
+
# Note: Because this method will convert any & symbols to the string "and",
|
124
|
+
# you should run any methods which convert HTML entities (convert_html_entities and convert_misc_entities)
|
125
|
+
# before running this method.
|
126
|
+
def convert_misc_characters
|
127
|
+
dummy = dup.gsub(/\.{3,}/, " dot dot dot ") # Catch ellipses before single dot rule!
|
128
|
+
{
|
129
|
+
/\s*&\s*/ => "and",
|
130
|
+
/\s*#/ => "number",
|
131
|
+
/\s*@\s*/ => "at",
|
132
|
+
/(\S|^)\.(\S)/ => '\1 dot \2',
|
133
|
+
/(\s|^)\$(\d*)(\s|$)/ => '\2 dollars',
|
134
|
+
/\s*\*\s*/ => "star",
|
135
|
+
/\s*%\s*/ => "percent",
|
136
|
+
/\s*(\\|\/)\s*/ => "slash",
|
137
|
+
}.each do |found, replaced|
|
138
|
+
replaced = " #{replaced} " unless replaced =~ /\\1/
|
139
|
+
dummy.gsub!(found, replaced)
|
140
|
+
end
|
141
|
+
dummy = dummy.gsub(/(^|\w)'(\w|$)/, '\1\2').gsub(/[\.,:;()\[\]\/\?!\^'"_]/, " ")
|
142
|
+
end
|
143
|
+
|
144
|
+
# Replace runs of whitespace in string. Defaults to a single space but any replacement
|
145
|
+
# string may be specified as an argument. Examples:
|
146
|
+
#
|
147
|
+
# "Foo bar".replace_whitespace # => "Foo bar"
|
148
|
+
# "Foo bar".replace_whitespace("-") # => "Foo-bar"
|
149
|
+
def replace_whitespace(replace = " ")
|
150
|
+
gsub(/\s+/, replace)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Removes specified character from the beginning and/or end of the string and then performs
|
154
|
+
# <tt>String#squeeze(character)</tt>, condensing runs of the character within the string.
|
155
|
+
#
|
156
|
+
# Note: This method has been superceded by ActiveSupport's squish method.
|
157
|
+
def collapse(character = " ")
|
158
|
+
sub(/^#{character}*/, "").sub(/#{character}*$/, "").squeeze(character)
|
159
|
+
end
|
160
|
+
|
161
|
+
end # class String
|
162
|
+
|
163
|
+
# EOF
|