webby 0.8.4 → 0.9.0
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 +19 -0
- data/Manifest.txt +104 -91
- data/README.txt +27 -45
- data/Rakefile +4 -5
- data/bin/webby +2 -1
- data/bin/webby-gen +8 -0
- data/{data/Rakefile → examples/blog/Sitefile} +0 -2
- data/examples/{webby → blog}/tasks/blog.rake +5 -4
- data/{data → examples/blog}/templates/atom_feed.erb +10 -11
- data/{data → examples/blog}/templates/blog/month.erb +1 -1
- data/{data → examples/blog}/templates/blog/post.erb +1 -0
- data/{data → examples/blog}/templates/blog/year.erb +1 -1
- data/examples/presentation/{Rakefile → Sitefile} +0 -4
- data/examples/presentation/content/{_sample_code.txt → presentation/_sample_code.txt} +0 -0
- data/examples/presentation/content/{index.txt → presentation/index.txt} +0 -0
- data/{data/content → examples/presentation/content/presentation}/s5/blank.gif +0 -0
- data/{data/content → examples/presentation/content/presentation}/s5/bodybg.gif +0 -0
- data/{data/content → examples/presentation/content/presentation}/s5/framing.css +0 -0
- data/{data/content → examples/presentation/content/presentation}/s5/iepngfix.htc +0 -0
- data/{data/content → examples/presentation/content/presentation}/s5/opera.css +0 -0
- data/{data/content → examples/presentation/content/presentation}/s5/outline.css +0 -0
- data/{data/content → examples/presentation/content/presentation}/s5/pretty.css +0 -0
- data/{data/content → examples/presentation/content/presentation}/s5/print.css +0 -0
- data/{data/content → examples/presentation/content/presentation}/s5/s5-core.css +0 -0
- data/{data/content → examples/presentation/content/presentation}/s5/slides.css +0 -0
- data/{data/content → examples/presentation/content/presentation}/s5/slides.js +0 -0
- data/examples/presentation/layouts/{presentation.rhtml → presentation.txt} +3 -3
- data/examples/presentation/templates/{_partial.erb → _code_partial.erb} +0 -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/{Rakefile → Sitefile} +2 -2
- data/examples/webby/content/communicate/index.txt +28 -0
- data/examples/webby/content/css/background.gif +0 -0
- data/examples/webby/content/css/site.css +52 -20
- data/examples/webby/content/index.txt +7 -8
- data/examples/webby/content/learn/index.txt +28 -0
- data/examples/webby/content/reference/index.txt +3 -1
- data/examples/webby/content/release-notes/rel-0-9-0/index.txt +73 -0
- data/examples/webby/content/sitemap.txt +31 -0
- data/examples/webby/content/tips_and_tricks/index.txt +1 -1
- data/examples/webby/content/tutorial/index.txt +17 -17
- data/examples/webby/content/{manual → user-manual}/index.txt +53 -50
- data/examples/webby/layouts/{default.rhtml → default.txt} +8 -15
- data/examples/webby/templates/page.erb +1 -1
- data/examples/website/Sitefile +7 -0
- data/{data → examples/website}/content/css/blueprint/License.txt +0 -0
- data/{data → examples/website}/content/css/blueprint/Readme.txt +0 -0
- data/{data → examples/website}/content/css/blueprint/compressed/print.css +0 -0
- data/{data → examples/website}/content/css/blueprint/compressed/screen.css +0 -0
- data/{data → examples/website}/content/css/blueprint/lib/forms.css +0 -0
- data/{data → examples/website}/content/css/blueprint/lib/grid.css +0 -0
- data/{data → examples/website}/content/css/blueprint/lib/grid.png +0 -0
- data/{data → examples/website}/content/css/blueprint/lib/ie.css +0 -0
- data/{data → examples/website}/content/css/blueprint/lib/reset.css +0 -0
- data/{data → examples/website}/content/css/blueprint/lib/typography.css +0 -0
- data/{data → examples/website}/content/css/blueprint/plugins/buttons/Readme +0 -0
- data/{data → examples/website}/content/css/blueprint/plugins/buttons/buttons.css +0 -0
- data/{data → examples/website}/content/css/blueprint/plugins/buttons/icons/cross.png +0 -0
- data/{data → examples/website}/content/css/blueprint/plugins/buttons/icons/key.png +0 -0
- data/{data → examples/website}/content/css/blueprint/plugins/buttons/icons/tick.png +0 -0
- data/{data → examples/website}/content/css/blueprint/plugins/css-classes/Readme +0 -0
- data/{data → examples/website}/content/css/blueprint/plugins/css-classes/css-classes.css +0 -0
- data/{data → examples/website}/content/css/blueprint/plugins/fancy-type/Readme +0 -0
- data/{data → examples/website}/content/css/blueprint/plugins/fancy-type/fancy-type-compressed.css +0 -0
- data/{data → examples/website}/content/css/blueprint/plugins/fancy-type/fancy-type.css +0 -0
- data/{data → examples/website}/content/css/blueprint/print.css +0 -0
- data/{data → examples/website}/content/css/blueprint/screen.css +0 -0
- data/{data → examples/website}/content/css/coderay.css +0 -0
- data/{data → examples/website}/content/css/site.css +0 -0
- data/{data → examples/website}/content/index.txt +2 -1
- data/{data/layouts/default.rhtml → examples/website/layouts/default.txt} +1 -1
- data/{data → examples/website}/lib/breadcrumbs.rb +0 -0
- data/{data → examples/website}/templates/_partial.erb +0 -0
- data/{data → examples/website}/templates/page.erb +0 -0
- data/{data → examples/website}/templates/presentation.erb +0 -0
- data/lib/webby/apps/generator.rb +283 -0
- data/lib/webby/apps/main.rb +221 -0
- data/lib/webby/apps.rb +12 -0
- data/lib/webby/builder.rb +8 -10
- data/lib/webby/core_ext/enumerable.rb +11 -0
- data/lib/webby/{utils.rb → core_ext/hash.rb} +2 -26
- data/lib/webby/core_ext/kernel.rb +21 -0
- data/lib/webby/core_ext/string.rb +163 -0
- data/lib/webby/core_ext/time.rb +9 -0
- data/lib/webby/filters/haml.rb +13 -5
- data/lib/webby/filters/markdown.rb +12 -4
- data/lib/webby/filters/outline.rb +3 -2
- data/lib/webby/filters/sass.rb +12 -4
- data/lib/webby/filters/textile.rb +12 -4
- data/lib/webby/filters/tidy.rb +10 -8
- data/lib/webby/filters.rb +2 -0
- data/lib/webby/helpers/graphviz_helper.rb +1 -2
- data/lib/webby/helpers/tex_img_helper.rb +6 -10
- data/lib/webby/renderer.rb +5 -3
- data/lib/webby/resources/layout.rb +1 -1
- data/lib/webby/resources/page.rb +1 -1
- data/lib/webby/resources/resource.rb +13 -3
- data/lib/webby/resources.rb +16 -0
- data/{data → lib/webby}/tasks/build.rake +0 -0
- data/{examples/presentation → lib/webby}/tasks/create.rake +1 -1
- data/{data → lib/webby}/tasks/deploy.rake +0 -0
- data/{examples → lib}/webby/tasks/growl.rake +4 -1
- data/{data → lib/webby}/tasks/heel.rake +0 -0
- data/{data → lib/webby}/tasks/validate.rake +0 -0
- data/lib/webby.rb +11 -5
- 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/webby/apps/generator_spec.rb +111 -0
- data/spec/webby/apps/main_spec.rb +75 -0
- data/spec/webby/helpers/capture_helper_spec.rb +1 -1
- data/spec/webby/resources_spec.rb +17 -0
- data/tasks/gem.rake +10 -2
- data/tasks/git.rake +41 -0
- data/tasks/rubyforge.rake +2 -2
- data/tasks/website.rake +38 -38
- metadata +125 -98
- data/data/tasks/blog.rake +0 -71
- data/data/tasks/create.rake +0 -22
- data/data/tasks/growl.rake +0 -12
- data/data/tasks/setup.rb +0 -17
- data/examples/presentation/content/s5/blank.gif +0 -0
- data/examples/presentation/content/s5/bodybg.gif +0 -0
- data/examples/presentation/content/s5/framing.css +0 -23
- data/examples/presentation/content/s5/iepngfix.htc +0 -42
- data/examples/presentation/content/s5/opera.css +0 -7
- data/examples/presentation/content/s5/outline.css +0 -15
- data/examples/presentation/content/s5/pretty.css +0 -86
- data/examples/presentation/content/s5/print.css +0 -1
- data/examples/presentation/content/s5/s5-core.css +0 -9
- data/examples/presentation/content/s5/slides.css +0 -3
- data/examples/presentation/content/s5/slides.js +0 -553
- data/examples/presentation/tasks/blog.rake +0 -71
- data/examples/presentation/tasks/build.rake +0 -27
- data/examples/presentation/tasks/deploy.rake +0 -22
- data/examples/presentation/tasks/growl.rake +0 -12
- data/examples/presentation/tasks/heel.rake +0 -28
- data/examples/presentation/tasks/setup.rb +0 -17
- data/examples/presentation/tasks/validate.rake +0 -19
- data/examples/webby/tasks/build.rake +0 -27
- data/examples/webby/tasks/create.rake +0 -22
- data/examples/webby/tasks/deploy.rake +0 -22
- data/examples/webby/tasks/heel.rake +0 -28
- data/examples/webby/tasks/setup.rb +0 -17
- data/examples/webby/tasks/validate.rake +0 -19
- data/lib/webby/main.rb +0 -227
|
@@ -0,0 +1,221 @@
|
|
|
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
|
+
# Create a new Main webby object for building websites.
|
|
16
|
+
#
|
|
17
|
+
def initialize
|
|
18
|
+
@stdout = $stdout
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Runs the main webby application. The command line arguments are passed
|
|
22
|
+
# in to this method as an array of strings. The command line arguments are
|
|
23
|
+
# parsed to figure out which rake task to invoke.
|
|
24
|
+
#
|
|
25
|
+
def run( args )
|
|
26
|
+
args = args.dup
|
|
27
|
+
|
|
28
|
+
parse args
|
|
29
|
+
init args
|
|
30
|
+
rake
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Parse the command line _args_ for options and commands to invoke.
|
|
34
|
+
#
|
|
35
|
+
def parse( args )
|
|
36
|
+
opts = OptionParser.new
|
|
37
|
+
opts.banner = 'Usage: webby [options] target [target args]'
|
|
38
|
+
|
|
39
|
+
opts.separator ''
|
|
40
|
+
opts.on('-D', '--describe [PATTERN]', 'describe the tasks (matching optional PATTERN), then exit') {|pattern| app.do_option('--describe', pattern)}
|
|
41
|
+
opts.on('-P', '--prereqs', 'display the tasks and dependencies, then exit') {app.do_option('--prereqs', nil)}
|
|
42
|
+
opts.on('-T', '--tasks [PATTERN]', 'display the tasks (matching optional PATTERN) with descriptions, then exit') {|pattern| app.do_option('--tasks', pattern)}
|
|
43
|
+
opts.on('-t', '--trace', 'turn on invoke/execute tracing, enable full backtrace') {app.do_option('--trace', nil)}
|
|
44
|
+
|
|
45
|
+
opts.separator ''
|
|
46
|
+
opts.separator 'common options:'
|
|
47
|
+
|
|
48
|
+
opts.on_tail( '-h', '--help', 'show this message' ) do
|
|
49
|
+
@stdout.puts opts
|
|
50
|
+
exit
|
|
51
|
+
end
|
|
52
|
+
opts.on_tail( '--version', 'show version' ) do
|
|
53
|
+
@stdout.puts "Webby #{::Webby::VERSION}"
|
|
54
|
+
exit
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
opts.parse! args
|
|
58
|
+
|
|
59
|
+
ARGV.replace Array(args.shift)
|
|
60
|
+
args.delete_if do |arg|
|
|
61
|
+
if %r/^[A-Z_]+=/ =~ arg
|
|
62
|
+
ARGV << arg
|
|
63
|
+
next true
|
|
64
|
+
end
|
|
65
|
+
false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
args
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Initialize the Rake application object and load the core rake tasks, the
|
|
72
|
+
# site specific rake tasks, and the site specific ruby code. Any extra
|
|
73
|
+
# command line arguments are converted into a page name and directory that
|
|
74
|
+
# might get created (depending upon the task invoked).
|
|
75
|
+
#
|
|
76
|
+
def init( args )
|
|
77
|
+
# Make sure we're in a folder with a Sitefile
|
|
78
|
+
app.do_option('--rakefile', 'Sitefile')
|
|
79
|
+
app.do_option('--nosearch', nil)
|
|
80
|
+
app.do_option('--silent', nil)
|
|
81
|
+
|
|
82
|
+
unless app.have_rakefile
|
|
83
|
+
raise RuntimeError, "Sitefile not found"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
import_default_tasks
|
|
87
|
+
import_website_tasks
|
|
88
|
+
require_lib_files
|
|
89
|
+
capture_command_line_args(args)
|
|
90
|
+
args
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Execute the rake command.
|
|
94
|
+
#
|
|
95
|
+
def rake
|
|
96
|
+
app.init 'webby'
|
|
97
|
+
app.load_rakefile
|
|
98
|
+
app.top_level
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Return the Rake application object.
|
|
102
|
+
#
|
|
103
|
+
def app
|
|
104
|
+
Rake.application
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Search for the "Sitefile" starting in the current directory and working
|
|
108
|
+
# upwards through the filesystem until the root of the filesystem is
|
|
109
|
+
# reached. If a "Sitefile" is not found, a RuntimeError is raised.
|
|
110
|
+
#
|
|
111
|
+
def find_sitefile
|
|
112
|
+
here = Dir.pwd
|
|
113
|
+
while ! app.have_rakefile
|
|
114
|
+
Dir.chdir("..")
|
|
115
|
+
if Dir.pwd == here || options.nosearch
|
|
116
|
+
fail "No Sitefile found"
|
|
117
|
+
end
|
|
118
|
+
here = Dir.pwd
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def import_default_tasks
|
|
123
|
+
Dir.glob(::Webby.libpath(%w[webby tasks *.rake])).sort.each {|fn| import fn}
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def import_website_tasks
|
|
127
|
+
Dir.glob(::File.join(%w[tasks *.rake])).sort.each {|fn| import fn}
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def require_lib_files
|
|
131
|
+
Dir.glob(::File.join(%w[lib ** *.rb])).sort.each {|fn| require fn}
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def capture_command_line_args(args)
|
|
135
|
+
args = OpenStruct.new(:raw => args)
|
|
136
|
+
|
|
137
|
+
if args.raw.size > 1
|
|
138
|
+
::Webby.deprecated "multiple arguments used for page title",
|
|
139
|
+
"please quote the page title"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
dashed = args.raw.join('-').downcase
|
|
143
|
+
spaced = args.raw.join(' ')
|
|
144
|
+
dir = ::File.dirname(dashed)
|
|
145
|
+
|
|
146
|
+
args.dir = ('.' == dir ? '' : dir)
|
|
147
|
+
args.slug = ::Webby::Resources::File.basename(dashed).to_url
|
|
148
|
+
args.title = ::Webby::Resources::File.basename(spaced).titlecase
|
|
149
|
+
|
|
150
|
+
# page should be dir/slug without leading /
|
|
151
|
+
args.page = ::File.join(args.dir, args.slug).gsub(/^\//, '')
|
|
152
|
+
|
|
153
|
+
::Webby.site.args = args
|
|
154
|
+
Object.const_set(:SITE, Webby.site)
|
|
155
|
+
args
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
end # class Main
|
|
159
|
+
end # module Webby::Apps
|
|
160
|
+
|
|
161
|
+
# :stopdoc:
|
|
162
|
+
# Monkey patches so that rake displays the correct application name in the
|
|
163
|
+
# help messages.
|
|
164
|
+
#
|
|
165
|
+
class Rake::Application
|
|
166
|
+
def display_prerequisites
|
|
167
|
+
tasks.each do |t|
|
|
168
|
+
puts "#{name} #{t.name}"
|
|
169
|
+
t.prerequisites.each { |pre| puts " #{pre}" }
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def display_tasks_and_comments
|
|
174
|
+
displayable_tasks = tasks.select { |t|
|
|
175
|
+
t.comment && t.name =~ options.show_task_pattern
|
|
176
|
+
}
|
|
177
|
+
if options.full_description
|
|
178
|
+
displayable_tasks.each do |t|
|
|
179
|
+
puts "#{name} #{t.name_with_args}"
|
|
180
|
+
t.full_comment.split("\n").each do |line|
|
|
181
|
+
puts " #{line}"
|
|
182
|
+
end
|
|
183
|
+
puts
|
|
184
|
+
end
|
|
185
|
+
else
|
|
186
|
+
width = displayable_tasks.collect { |t| t.name_with_args.length }.max || 10
|
|
187
|
+
max_column = 80 - name.size - width - 7
|
|
188
|
+
displayable_tasks.each do |t|
|
|
189
|
+
printf "#{name} %-#{width}s # %s\n",
|
|
190
|
+
t.name_with_args, truncate(t.comment, max_column)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Provide standard execption handling for the given block.
|
|
196
|
+
def standard_exception_handling
|
|
197
|
+
begin
|
|
198
|
+
yield
|
|
199
|
+
rescue SystemExit => ex
|
|
200
|
+
# Exit silently with current status
|
|
201
|
+
exit(ex.status)
|
|
202
|
+
rescue SystemExit, GetoptLong::InvalidOption => ex
|
|
203
|
+
# Exit silently
|
|
204
|
+
exit(1)
|
|
205
|
+
rescue Exception => ex
|
|
206
|
+
# Exit with error message
|
|
207
|
+
$stderr.puts "webby aborted!"
|
|
208
|
+
$stderr.puts ex.message
|
|
209
|
+
if options.trace
|
|
210
|
+
$stderr.puts ex.backtrace.join("\n")
|
|
211
|
+
else
|
|
212
|
+
$stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
|
|
213
|
+
$stderr.puts "(See full trace by running task with --trace)"
|
|
214
|
+
end
|
|
215
|
+
exit(1)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end # class Rake::Application
|
|
219
|
+
# :startdoc:
|
|
220
|
+
|
|
221
|
+
# EOF
|
data/lib/webby/apps.rb
ADDED
data/lib/webby/builder.rb
CHANGED
|
@@ -69,19 +69,17 @@ class Builder
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
# call-seq:
|
|
72
|
-
# Builder.new_page_info
|
|
72
|
+
# Builder.new_page_info => [page, title, directory]
|
|
73
73
|
#
|
|
74
|
-
def new_page_info
|
|
75
|
-
|
|
74
|
+
def new_page_info
|
|
75
|
+
args = Webby.site.args
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
dir = ::File.dirname(page)
|
|
82
|
-
dir = '' if dir == '.'
|
|
77
|
+
if args.raw.empty?
|
|
78
|
+
task_name = Rake.application.top_level_tasks.first
|
|
79
|
+
raise "Usage: webby #{task_name} path"
|
|
80
|
+
end
|
|
83
81
|
|
|
84
|
-
|
|
82
|
+
[args.page, args.title, args.dir]
|
|
85
83
|
end
|
|
86
84
|
|
|
87
85
|
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
# :stopdoc:
|
|
2
|
-
module Enumerable
|
|
3
|
-
def injecting( initial )
|
|
4
|
-
inject(initial) do |memo, obj|
|
|
5
|
-
yield(memo, obj); memo
|
|
6
|
-
end
|
|
7
|
-
end
|
|
8
|
-
end
|
|
9
1
|
|
|
10
2
|
class Hash
|
|
3
|
+
|
|
11
4
|
def sanitize!
|
|
12
5
|
h = self.injecting({}) do |h, (k, v)|
|
|
13
6
|
h[k] = case v
|
|
@@ -30,23 +23,6 @@ class Hash
|
|
|
30
23
|
self.each {|k,v| h[k.to_sym] = v}
|
|
31
24
|
return h
|
|
32
25
|
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
class String
|
|
36
|
-
def underscore
|
|
37
|
-
self.
|
|
38
|
-
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
|
39
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
|
40
|
-
tr(" -", "__").
|
|
41
|
-
downcase
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
class Time
|
|
46
|
-
def to_y
|
|
47
|
-
self.to_yaml.slice(4..-1).strip
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
# :startdoc:
|
|
26
|
+
end # class Hash
|
|
51
27
|
|
|
52
28
|
# EOF
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
end # module Kernel
|
|
20
|
+
|
|
21
|
+
# 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
|
data/lib/webby/filters/haml.rb
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
try_require 'haml'
|
|
2
1
|
|
|
3
2
|
# Render text via the Haml library
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
if try_require('haml', 'haml')
|
|
4
|
+
|
|
5
|
+
Webby::Filters.register :haml do |input, cursor|
|
|
6
|
+
opts = ::Webby.site.haml_options.merge(cursor.page.haml_options || {})
|
|
7
|
+
b = cursor.renderer.get_binding
|
|
8
|
+
Haml::Engine.new(input, opts).to_html(b)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Otherwise raise an error if the user tries to use haml
|
|
12
|
+
else
|
|
13
|
+
Webby::Filters.register :haml do |input, cursor|
|
|
14
|
+
raise Webby::Error, "'haml' must be installed to use the haml filter"
|
|
15
|
+
end
|
|
8
16
|
end
|
|
9
17
|
|
|
10
18
|
# EOF
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
try_require 'bluecloth'
|
|
2
1
|
|
|
3
|
-
# Render text via markdown using the
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
# Render text via markdown using the RDiscount library.
|
|
3
|
+
if try_require('rdiscount', 'rdiscount')
|
|
4
|
+
|
|
5
|
+
Webby::Filters.register :markdown do |input|
|
|
6
|
+
RDiscount.new(input).to_html
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Otherwise raise an error if the user tries to use markdown
|
|
10
|
+
else
|
|
11
|
+
Webby::Filters.register :markdown do |input|
|
|
12
|
+
raise Webby::Error, "'rdiscount' must be installed to use the markdown filter"
|
|
13
|
+
end
|
|
6
14
|
end
|
|
7
15
|
|
|
8
16
|
# EOF
|
|
@@ -112,7 +112,7 @@ class Outline
|
|
|
112
112
|
# the table of contents -- "Get Fuzzy" in this example.
|
|
113
113
|
#
|
|
114
114
|
def filter
|
|
115
|
-
doc = Hpricot(@str)
|
|
115
|
+
doc = Hpricot.XML(@str)
|
|
116
116
|
|
|
117
117
|
# extract directives from the "toc" tag
|
|
118
118
|
toc_elem = doc.search('toc').first
|
|
@@ -132,7 +132,8 @@ class Outline
|
|
|
132
132
|
@toc_range = Integer(m[1])..Integer(m[2])
|
|
133
133
|
@list_opening = build_list_opening(toc_elem)
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
headers = @toc_range.map {|x| "h#{x}"}
|
|
136
|
+
doc.traverse_element(*headers) do |elem|
|
|
136
137
|
text, id = heading_info(elem)
|
|
137
138
|
add_to_toc(text, id) if @toc_range.include? current_level
|
|
138
139
|
end
|
data/lib/webby/filters/sass.rb
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
try_require 'sass'
|
|
2
1
|
|
|
3
2
|
# Render text via the Sass library (part of Haml)
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
if try_require('sass', 'haml')
|
|
4
|
+
|
|
5
|
+
Webby::Filters.register :sass do |input, cursor|
|
|
6
|
+
opts = ::Webby.site.sass_options.merge(cursor.page.sass_options || {})
|
|
7
|
+
Sass::Engine.new(input, opts).render
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Otherwise raise an error if the user tries to use sass
|
|
11
|
+
else
|
|
12
|
+
Webby::Filters.register :sass do |input, cursor|
|
|
13
|
+
raise Webby::Error, "'haml' must be installed to use the sass filter"
|
|
14
|
+
end
|
|
7
15
|
end
|
|
8
16
|
|
|
9
17
|
# EOF
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
try_require 'redcloth'
|
|
2
1
|
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
# If RedCloth is installed, then configure the textile filter
|
|
3
|
+
if try_require('redcloth', 'RedCloth')
|
|
4
|
+
|
|
5
|
+
Webby::Filters.register :textile do |input|
|
|
6
|
+
RedCloth.new(input, %w(no_span_caps)).to_html
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Otherwise raise an error if the user tries to use textile
|
|
10
|
+
else
|
|
11
|
+
Webby::Filters.register :textile do |input|
|
|
12
|
+
raise Webby::Error, "'RedCloth' must be installed to use the textile filter"
|
|
13
|
+
end
|
|
6
14
|
end
|
|
7
15
|
|
|
8
16
|
# EOF
|
data/lib/webby/filters/tidy.rb
CHANGED
|
@@ -41,11 +41,6 @@ class Tidy
|
|
|
41
41
|
# created and output Tidy formatted HTML or XHTML.
|
|
42
42
|
#
|
|
43
43
|
def process
|
|
44
|
-
%x[tidy -v 2>&1]
|
|
45
|
-
unless 0 == $?.exitstatus
|
|
46
|
-
raise NameError, "'tidy' not found on the path"
|
|
47
|
-
end
|
|
48
|
-
|
|
49
44
|
cmd = "tidy %s -q -f #{@err.path}" % ::Webby.site.tidy_options
|
|
50
45
|
out = IO.popen(cmd, 'r+') do |tidy|
|
|
51
46
|
tidy.write @str
|
|
@@ -63,9 +58,16 @@ class Tidy
|
|
|
63
58
|
end # class Tidy
|
|
64
59
|
|
|
65
60
|
# Render html into html/xhtml via the Tidy program
|
|
66
|
-
|
|
67
|
-
register :tidy do |input|
|
|
68
|
-
|
|
61
|
+
if cmd_available? %w[tidy -v]
|
|
62
|
+
register :tidy do |input|
|
|
63
|
+
Filters::Tidy.new(input).process
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Otherwise raise an error if the user tries to use tidy
|
|
67
|
+
else
|
|
68
|
+
register :tidy do |input|
|
|
69
|
+
raise Webby::Error, "'tidy' must be installed to use the tidy filter"
|
|
70
|
+
end
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
end # module Filters
|
data/lib/webby/filters.rb
CHANGED
|
@@ -50,6 +50,8 @@ module Filters
|
|
|
50
50
|
@renderer.instance_variable_set(:@_cursor, self)
|
|
51
51
|
filters.inject(input) do |result, filter|
|
|
52
52
|
handler = Filters[filter]
|
|
53
|
+
raise ::Webby::Error, "unknown filter: #{filter.inspect}" if handler.nil?
|
|
54
|
+
|
|
53
55
|
args = [result, self][0, handler.arity]
|
|
54
56
|
handle(filter, handler, *args)
|
|
55
57
|
end
|