webby 0.8.4 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|