proton 0.3.0.rc1
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/AUTHORS +6 -0
- data/HISTORY.md +200 -0
- data/README.md +75 -0
- data/Rakefile +5 -0
- data/TODO.md +6 -0
- data/bin/proton +7 -0
- data/data/new_site/Protonfile +12 -0
- data/data/new_site/README.md +10 -0
- data/data/new_site/_layouts/default.haml +28 -0
- data/data/new_site/index.haml +5 -0
- data/data/rack/Gemfile +2 -0
- data/data/rack/Gemfile.lock +40 -0
- data/data/rack/config.ru +24 -0
- data/lib/proton.rb +78 -0
- data/lib/proton/cli.rb +227 -0
- data/lib/proton/cli/helpers.rb +89 -0
- data/lib/proton/compass_support.rb +8 -0
- data/lib/proton/config.rb +116 -0
- data/lib/proton/helpers.rb +126 -0
- data/lib/proton/layout.rb +20 -0
- data/lib/proton/meta.rb +17 -0
- data/lib/proton/page.rb +431 -0
- data/lib/proton/partial.rb +12 -0
- data/lib/proton/project.rb +176 -0
- data/lib/proton/server.rb +99 -0
- data/lib/proton/set.rb +32 -0
- data/lib/proton/version.rb +13 -0
- data/test/fixture/build_options/control/page.html +0 -0
- data/test/fixture/build_options/control/style.css +1 -0
- data/test/fixture/build_options/hyde.conf +18 -0
- data/test/fixture/build_options/site/page.haml +0 -0
- data/test/fixture/build_options/site/style.scss +1 -0
- data/test/fixture/compass/hyde.conf +4 -0
- data/test/fixture/compass/site/style.scss +5 -0
- data/test/fixture/empty_config/hyde.conf +0 -0
- data/test/fixture/extensions/control/index.html +1 -0
- data/test/fixture/extensions/extensions/a/a.rb +1 -0
- data/test/fixture/extensions/extensions/hi.rb +1 -0
- data/test/fixture/extensions/hyde.conf +8 -0
- data/test/fixture/extensions/site/index.haml +1 -0
- data/test/fixture/fail_type/control/about/index.html +2 -0
- data/test/fixture/fail_type/control/about/us.html +2 -0
- data/test/fixture/fail_type/control/index.html +1 -0
- data/test/fixture/fail_type/hyde.conf +8 -0
- data/test/fixture/fail_type/site/index.haml +4 -0
- data/test/fixture/high_version/hyde.conf +1 -0
- data/test/fixture/high_version_2/hyde.conf +1 -0
- data/test/fixture/html/control/index.html +2 -0
- data/test/fixture/html/hyde.conf +8 -0
- data/test/fixture/html/site/index.html +2 -0
- data/test/fixture/ignores/control/about.html +1 -0
- data/test/fixture/ignores/hyde.conf +10 -0
- data/test/fixture/ignores/site/about.haml +1 -0
- data/test/fixture/ignores/site/hi.haml +1 -0
- data/test/fixture/metadata/control/index.html +4 -0
- data/test/fixture/metadata/hyde.conf +8 -0
- data/test/fixture/metadata/site/index.haml +8 -0
- data/test/fixture/nested_layout/control/index.html +2 -0
- data/test/fixture/nested_layout/hyde.conf +9 -0
- data/test/fixture/nested_layout/layouts/default.haml +2 -0
- data/test/fixture/nested_layout/layouts/post.haml +3 -0
- data/test/fixture/nested_layout/site/index.haml +4 -0
- data/test/fixture/one/control/about/index.css +1 -0
- data/test/fixture/one/control/about/us.html +1 -0
- data/test/fixture/one/control/cheers.html +5 -0
- data/test/fixture/one/control/css/bar.css +0 -0
- data/test/fixture/one/control/css/style.css +1 -0
- data/test/fixture/one/control/hello.html +5 -0
- data/test/fixture/one/control/hi.html +1 -0
- data/test/fixture/one/control/images/bar.gif +0 -0
- data/test/fixture/one/control/images/baz.png +0 -0
- data/test/fixture/one/control/images/foo.jpg +0 -0
- data/test/fixture/one/control/index.html +7 -0
- data/test/fixture/one/hyde.conf +9 -0
- data/test/fixture/one/layouts/default.haml +4 -0
- data/test/fixture/one/partials/menu.haml +3 -0
- data/test/fixture/one/public/about/index.css +1 -0
- data/test/fixture/one/public/about/us.html +1 -0
- data/test/fixture/one/public/cheers.html +5 -0
- data/test/fixture/one/public/css/bar.css +0 -0
- data/test/fixture/one/public/css/style.css +1 -0
- data/test/fixture/one/public/hello.html +5 -0
- data/test/fixture/one/public/hi.html +1 -0
- data/test/fixture/one/public/images/bar.gif +0 -0
- data/test/fixture/one/public/images/baz.png +0 -0
- data/test/fixture/one/public/images/foo.jpg +0 -0
- data/test/fixture/one/public/index.html +7 -0
- data/test/fixture/one/site/about/index.scss +1 -0
- data/test/fixture/one/site/about/us.haml +3 -0
- data/test/fixture/one/site/cheers.html.haml +1 -0
- data/test/fixture/one/site/css/bar.scss +0 -0
- data/test/fixture/one/site/css/style.scss +2 -0
- data/test/fixture/one/site/hello.haml +3 -0
- data/test/fixture/one/site/hi.html +3 -0
- data/test/fixture/one/site/images/bar.gif +0 -0
- data/test/fixture/one/site/images/baz.png +0 -0
- data/test/fixture/one/site/images/foo.jpg +0 -0
- data/test/fixture/one/site/index.haml +7 -0
- data/test/fixture/parent/control/about/index.html +2 -0
- data/test/fixture/parent/control/about/us.html +2 -0
- data/test/fixture/parent/control/index.html +1 -0
- data/test/fixture/parent/hyde.conf +8 -0
- data/test/fixture/parent/site/about/index.haml +3 -0
- data/test/fixture/parent/site/about/us.haml +3 -0
- data/test/fixture/parent/site/index.haml +3 -0
- data/test/fixture/sort/control/about.html +6 -0
- data/test/fixture/sort/control/about/hardy.html +1 -0
- data/test/fixture/sort/control/about/intrepid.html +1 -0
- data/test/fixture/sort/hyde.conf +8 -0
- data/test/fixture/sort/site/about.haml +3 -0
- data/test/fixture/sort/site/about/hardy.haml +4 -0
- data/test/fixture/sort/site/about/intrepid.haml +4 -0
- data/test/fixture/subclass/control/index.html +1 -0
- data/test/fixture/subclass/extensions/a/a.rb +12 -0
- data/test/fixture/subclass/hyde.conf +9 -0
- data/test/fixture/subclass/layouts/default.haml +1 -0
- data/test/fixture/subclass/layouts/post.haml +1 -0
- data/test/fixture/subclass/site/index.haml +4 -0
- data/test/helper.rb +36 -0
- data/test/unit/build_options_test.rb +18 -0
- data/test/unit/extensions_test.rb +17 -0
- data/test/unit/fixture_test.rb +122 -0
- data/test/unit/page_test.rb +58 -0
- data/test/unit/proton_test.rb +27 -0
- data/test/unit/set_test.rb +26 -0
- metadata +301 -0
data/lib/proton/cli.rb
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# Class: Proton::CLI (Proton)
|
|
2
|
+
# Command line runner.
|
|
3
|
+
|
|
4
|
+
class Proton
|
|
5
|
+
class CLI < Shake
|
|
6
|
+
autoload :Helpers, "#{PREFIX}/proton/cli/helpers"
|
|
7
|
+
|
|
8
|
+
extend Helpers
|
|
9
|
+
include Defaults
|
|
10
|
+
|
|
11
|
+
task(:create) do
|
|
12
|
+
wrong_usage unless params.size == 1
|
|
13
|
+
template = File.expand_path('../../../data/new_site', __FILE__)
|
|
14
|
+
target = params.first
|
|
15
|
+
|
|
16
|
+
if target == '.'
|
|
17
|
+
pass "This is already a Proton project." if @protonfile
|
|
18
|
+
FileUtils.cp_r File.join(template, 'Protonfile'), target
|
|
19
|
+
say_status :create, 'Protonfile'
|
|
20
|
+
pass
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
pass "Error: target directory already exists." if File.directory?(target)
|
|
24
|
+
|
|
25
|
+
puts "Creating files in #{target}:"
|
|
26
|
+
puts
|
|
27
|
+
|
|
28
|
+
FileUtils.cp_r template, target
|
|
29
|
+
Dir[File.join(target, '**', '*')].sort.each do |f|
|
|
30
|
+
say_status :create, f if File.file?(f)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
puts ""
|
|
34
|
+
puts "Done! You've created a new project in #{target}."
|
|
35
|
+
puts "Get started now:"
|
|
36
|
+
puts ""
|
|
37
|
+
puts " $ cd #{target}"
|
|
38
|
+
puts " $ #{executable} start"
|
|
39
|
+
puts ""
|
|
40
|
+
puts "Or build the HTML files:"
|
|
41
|
+
puts ""
|
|
42
|
+
puts " $ #{executable} build"
|
|
43
|
+
puts ""
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
task.description = "Starts a new Proton project"
|
|
47
|
+
task.usage = "create NAME"
|
|
48
|
+
task.category = :create
|
|
49
|
+
|
|
50
|
+
task(:build) do
|
|
51
|
+
pre = project.config.output_path
|
|
52
|
+
|
|
53
|
+
project.build { |page|
|
|
54
|
+
c, handler = if page.tilt?
|
|
55
|
+
[ 33, "#{page.tilt_engine_name.downcase}" ]
|
|
56
|
+
else
|
|
57
|
+
[ 30, '*' ]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
puts ("\033[0;#{c}m%10s\033[0;32m #{pre}\033[0;m%s" % [ handler, page.path ]).strip
|
|
61
|
+
}
|
|
62
|
+
project.send :build_cleanup
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
task.description = "Builds the current project"
|
|
66
|
+
task.category = :project
|
|
67
|
+
|
|
68
|
+
task(:start) do
|
|
69
|
+
project
|
|
70
|
+
|
|
71
|
+
port = (params.extract('-p') || 4833).to_i
|
|
72
|
+
host = (params.extract('-o') || '0.0.0.0')
|
|
73
|
+
daemon = (!! params.delete('-D'))
|
|
74
|
+
|
|
75
|
+
require 'proton/server'
|
|
76
|
+
|
|
77
|
+
if daemon
|
|
78
|
+
pid = fork { Proton::Server.run! :Host => host, :Port => port, :quiet => true }
|
|
79
|
+
sleep 2
|
|
80
|
+
puts
|
|
81
|
+
puts "Listening on #{host}:#{port} on pid #{pid}."
|
|
82
|
+
puts "To stop: kill #{pid}"
|
|
83
|
+
else
|
|
84
|
+
Proton::Server.run! :Host => host, :Port => port
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
task.description = "Starts the server"
|
|
89
|
+
task.category = :project
|
|
90
|
+
task.help = %{
|
|
91
|
+
Usage:
|
|
92
|
+
|
|
93
|
+
#{executable} start [-p PORT] [-o HOST] [-D]
|
|
94
|
+
|
|
95
|
+
Starts an HTTP server so you may rapidly test your project locally.
|
|
96
|
+
|
|
97
|
+
If the -p and/or -o is specified, it will listen on the specified HOST:PORT.
|
|
98
|
+
Otherwise, the default is 0.0.0.0:4833.
|
|
99
|
+
|
|
100
|
+
If -D is specified, it goes into daemon mode.
|
|
101
|
+
}.gsub(/^ {4}/, '').strip.split("\n")
|
|
102
|
+
|
|
103
|
+
task(:rack) do
|
|
104
|
+
project
|
|
105
|
+
|
|
106
|
+
from = File.expand_path("#{PREFIX}/../data/rack/*")
|
|
107
|
+
files = Dir[from]
|
|
108
|
+
|
|
109
|
+
files.each do |f|
|
|
110
|
+
FileUtils.cp f, '.'
|
|
111
|
+
say_status :create, File.basename(f)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
task.description = "Makes a project Rack-compatible."
|
|
116
|
+
task.category = :project
|
|
117
|
+
|
|
118
|
+
task(:version) do
|
|
119
|
+
puts "Proton #{Proton::VERSION}"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
task.description = "Shows the current version"
|
|
123
|
+
task.category = :misc
|
|
124
|
+
|
|
125
|
+
task(:help) do
|
|
126
|
+
show_help_for(params.first) and pass if params.any?
|
|
127
|
+
|
|
128
|
+
show_task = Proc.new { |name, t| err " %-20s %s" % [ t.usage || name, t.description ] }
|
|
129
|
+
|
|
130
|
+
err "Usage: #{executable} <command>"
|
|
131
|
+
|
|
132
|
+
unless project?
|
|
133
|
+
err "\nCommands:"
|
|
134
|
+
tasks_for(:create).each &show_task
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
if project?
|
|
138
|
+
err "\nProject commands:"
|
|
139
|
+
tasks_for(:project).each &show_task
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
if other_tasks.any?
|
|
143
|
+
err "\nOthers:"
|
|
144
|
+
other_tasks.each &show_task
|
|
145
|
+
end
|
|
146
|
+
err "\nMisc commands:"
|
|
147
|
+
tasks_for(:misc).each &show_task
|
|
148
|
+
|
|
149
|
+
unless project?
|
|
150
|
+
err
|
|
151
|
+
err "Get started by typing:"
|
|
152
|
+
err " $ #{executable} create my_project"
|
|
153
|
+
end
|
|
154
|
+
err
|
|
155
|
+
err "Type `#{executable} help COMMAND` for additional help on a command."
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
task.description = "Shows help for a given command"
|
|
159
|
+
task.usage = "help [COMMAND]"
|
|
160
|
+
task.category = :misc
|
|
161
|
+
|
|
162
|
+
invalid do
|
|
163
|
+
task = task(command)
|
|
164
|
+
if task
|
|
165
|
+
err "Invalid usage."
|
|
166
|
+
err "Try: #{executable} #{task.usage}"
|
|
167
|
+
err
|
|
168
|
+
err "Type `#{executable} help` for more info."
|
|
169
|
+
else
|
|
170
|
+
err "Invalid command: #{command}"
|
|
171
|
+
err "Type `#{executable} help` for more info."
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def self.run(*argv)
|
|
176
|
+
return invoke(:version) if argv == ['-v'] || argv == ['--version']
|
|
177
|
+
trace = (!!argv.delete('--trace'))
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
begin
|
|
181
|
+
super *argv
|
|
182
|
+
|
|
183
|
+
rescue SyntaxError => e
|
|
184
|
+
raise e if trace
|
|
185
|
+
err
|
|
186
|
+
say_error e.message.split("\n").last
|
|
187
|
+
err
|
|
188
|
+
say_error "You have a syntax error."
|
|
189
|
+
say_info "Use --trace for more info."
|
|
190
|
+
|
|
191
|
+
# Convert 'can't load redcloth' to a friendly 'please gem install RedCloth'
|
|
192
|
+
rescue LoadError => e
|
|
193
|
+
raise e if trace
|
|
194
|
+
show_needed_gem gem_name(e)
|
|
195
|
+
|
|
196
|
+
# Print generic errors as something friendlier
|
|
197
|
+
rescue => e
|
|
198
|
+
raise e if trace
|
|
199
|
+
|
|
200
|
+
# Can't assume that HAML is always available.
|
|
201
|
+
if Object.const_defined?(:Haml) && e.is_a?(Haml::Error)
|
|
202
|
+
# Convert HAML's "Can't run XX filter; required 'yy'" messages
|
|
203
|
+
# to something friendlier
|
|
204
|
+
needed = %w(rdiscount stringio sass/plugin redcloth)
|
|
205
|
+
needed.detect { |what| show_needed_gem(what) && true if e.message.include?(what) }
|
|
206
|
+
else
|
|
207
|
+
err
|
|
208
|
+
say_error "#{e.class}: #{e.message}"
|
|
209
|
+
say_info "#{e.backtrace.first}"
|
|
210
|
+
err
|
|
211
|
+
say_error "Oops! An error occured."
|
|
212
|
+
say_info "Use --trace for more info."
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def self.find_config_file
|
|
218
|
+
Proton::CONFIG_FILES.inject(nil) { |a, fname| a ||= find_in_project(fname) }
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def self.run!(options={})
|
|
222
|
+
@config_file = options[:file] || find_config_file
|
|
223
|
+
Proton::Project.new rescue nil
|
|
224
|
+
super *[]
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
class Proton
|
|
2
|
+
class CLI
|
|
3
|
+
module Helpers
|
|
4
|
+
def show_help_for(name)
|
|
5
|
+
task = task(name)
|
|
6
|
+
pass "No such command. Try: #{executable} help" unless task
|
|
7
|
+
|
|
8
|
+
help = task.help
|
|
9
|
+
if help
|
|
10
|
+
help.each { |line| err line }
|
|
11
|
+
err
|
|
12
|
+
else
|
|
13
|
+
err "Usage: #{executable} #{task.usage || name}"
|
|
14
|
+
err "#{task.description}." if task.description
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def tasks_for(category)
|
|
19
|
+
tasks.select { |name, t| t.category == category }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def other_tasks
|
|
23
|
+
tasks.select { |name, t| t.category.nil? }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def say_info(str)
|
|
27
|
+
say_status '*', str, 30
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def say_error(str)
|
|
31
|
+
say_status 'error', str, 31
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def say_status(what, cmd, color=32)
|
|
35
|
+
c1 = "\033[0;#{color}m"
|
|
36
|
+
c0 = "\033[0;m"
|
|
37
|
+
puts "#{c1}%10s#{c0} %s" % [ what, cmd ]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def show_needed_gem(name)
|
|
41
|
+
err
|
|
42
|
+
say_error "You will need additional gems for this project."
|
|
43
|
+
say_info "To install: gem install #{name}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def no_project
|
|
47
|
+
"Error: no Proton config file found.\n" +
|
|
48
|
+
"(Looked for #{Proton::CONFIG_FILES.join(', ')})\n\n" +
|
|
49
|
+
"You start by creating a config file for this project:\n" +
|
|
50
|
+
" $ #{executable} create .\n\n" +
|
|
51
|
+
"You may also create an empty project in a new directory:\n" +
|
|
52
|
+
" $ #{executable} create NAME\n"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def project?
|
|
56
|
+
!! @config_file
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Gets the gem name from a LoadError exception.
|
|
60
|
+
def gem_name(e)
|
|
61
|
+
name = e.message.split(' ').last
|
|
62
|
+
name = 'RedCloth' if name == 'redcloth'
|
|
63
|
+
name = 'haml' if name == 'sass/plugin'
|
|
64
|
+
name
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def project
|
|
68
|
+
@project ||= begin
|
|
69
|
+
pass no_project unless project?
|
|
70
|
+
Dir.chdir File.dirname(@config_file)
|
|
71
|
+
|
|
72
|
+
begin
|
|
73
|
+
project = Proton.project || Proton::Project.new
|
|
74
|
+
pass no_project unless project.config_file
|
|
75
|
+
rescue LegacyError
|
|
76
|
+
err "This is a legacy Hyde project."
|
|
77
|
+
err "To force it, try editing `hyde.conf` and upgrade the version line to `hyde_requirement: 0.1`."
|
|
78
|
+
pass
|
|
79
|
+
rescue VersionError => e
|
|
80
|
+
err e.message
|
|
81
|
+
pass
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
project
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
class Proton
|
|
2
|
+
# Class: Proton::Config
|
|
3
|
+
# Configuration.
|
|
4
|
+
#
|
|
5
|
+
# ## Common usage
|
|
6
|
+
#
|
|
7
|
+
# Access it via `Proton.project`.
|
|
8
|
+
#
|
|
9
|
+
# Proton.project.config
|
|
10
|
+
#
|
|
11
|
+
# You may access config variables as attributes.
|
|
12
|
+
#
|
|
13
|
+
# Proton.project.config.site_path
|
|
14
|
+
# Proton.project.config.layouts_path
|
|
15
|
+
# Proton.project.config.extensions_path
|
|
16
|
+
# Proton.project.config.output_path
|
|
17
|
+
#
|
|
18
|
+
# Tilt options:
|
|
19
|
+
#
|
|
20
|
+
# Proton.project.config.tilt_options('sass')[:load_path]
|
|
21
|
+
# Proton.project.config.tilt_options_for('filename.haml')[:style]
|
|
22
|
+
#
|
|
23
|
+
class Config
|
|
24
|
+
DEFAULTS = {
|
|
25
|
+
:site_path => '.',
|
|
26
|
+
:layouts_path => '_layouts',
|
|
27
|
+
:extensions_path => '_extensions',
|
|
28
|
+
:partials_path => '_layouts',
|
|
29
|
+
:output_path => '_output',
|
|
30
|
+
:tilt_options => {
|
|
31
|
+
:haml => {
|
|
32
|
+
:escape_html => true
|
|
33
|
+
},
|
|
34
|
+
:sass => {
|
|
35
|
+
:load_paths => ['css', '.'],
|
|
36
|
+
:style => :compact,
|
|
37
|
+
:line_numbers => true
|
|
38
|
+
},
|
|
39
|
+
:scss => {
|
|
40
|
+
:load_paths => ['css', '.'],
|
|
41
|
+
:style => :compact,
|
|
42
|
+
:line_numbers => true
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
:tilt_build_options => {
|
|
46
|
+
:scss => {
|
|
47
|
+
:style => :compressed,
|
|
48
|
+
:line_numbers => false
|
|
49
|
+
},
|
|
50
|
+
:sass => {
|
|
51
|
+
:style => :compressed,
|
|
52
|
+
:line_numbers => false
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
def self.load(config_file)
|
|
58
|
+
new(YAML::load_file(config_file)) rescue new
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def initialize(options={})
|
|
62
|
+
# Try to emulate proper .merge behavior in Ruby 1.8
|
|
63
|
+
#DEFAULTS.each { |k, v| options[k] ||= v }
|
|
64
|
+
@table = Hashie::Mash.new
|
|
65
|
+
@table.deep_merge! DEFAULTS
|
|
66
|
+
@table.deep_merge! options
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Passthru
|
|
70
|
+
def method_missing(meth, *args, &blk)
|
|
71
|
+
@table.send meth, *args
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def requirement
|
|
75
|
+
# Backward compatibility: this config option used to be called
|
|
76
|
+
# `hyde_requirement` before the project was renamed to Proton.
|
|
77
|
+
self[:requirement] || self[:hyde_requirement]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Method: tilt_options_for (Proton::Config)
|
|
81
|
+
# Returns tilt options for a given file.
|
|
82
|
+
#
|
|
83
|
+
# ## Usage
|
|
84
|
+
# tilt_options_for(filename, options={})
|
|
85
|
+
#
|
|
86
|
+
# ## Example
|
|
87
|
+
# tilt_options_for('index.haml') # { :escape_html => ... }
|
|
88
|
+
#
|
|
89
|
+
def tilt_options_for(file, options={})
|
|
90
|
+
ext = file.split('.').last.downcase
|
|
91
|
+
opts = tilt_options(ext) || Hash.new
|
|
92
|
+
opts = opts.merge(tilt_options(ext, :tilt_build_options)) if options[:build]
|
|
93
|
+
|
|
94
|
+
to_hash opts
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Method: tilt_options (Proton::Config)
|
|
98
|
+
# Returns tilt options for a given engine.
|
|
99
|
+
#
|
|
100
|
+
# ## Usage
|
|
101
|
+
# tilt_options(engine_name)
|
|
102
|
+
#
|
|
103
|
+
# ## Example
|
|
104
|
+
# tilt_options('haml') # { :escape_html => ... }
|
|
105
|
+
#
|
|
106
|
+
def tilt_options(what, key=:tilt_options)
|
|
107
|
+
@table[key] ||= Hash.new
|
|
108
|
+
@table[key][what.to_s] ||= Hash.new
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
def to_hash(mash)
|
|
113
|
+
mash.inject(Hash.new) { |h, (k, v)| h[k.to_sym] = v; h }
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Module: Proton::Helpers (Proton)
|
|
2
|
+
# Helpers you can use in your pages.
|
|
3
|
+
#
|
|
4
|
+
# ## Creating your own helpers
|
|
5
|
+
# To create for own helpers, make an extension. See [Extending Proton:
|
|
6
|
+
# Helpers][1] for more info.
|
|
7
|
+
#
|
|
8
|
+
# [1]: /extending/helpers.html
|
|
9
|
+
|
|
10
|
+
class Proton
|
|
11
|
+
module Helpers
|
|
12
|
+
|
|
13
|
+
# Method: partial (Proton::Helpers)
|
|
14
|
+
# Renders a partial.
|
|
15
|
+
#
|
|
16
|
+
# ## Usage
|
|
17
|
+
# <%= partial path, locals %>
|
|
18
|
+
#
|
|
19
|
+
# ## Description
|
|
20
|
+
# See [Introduction: Partials](/introduction/partials.html) for more
|
|
21
|
+
# info.
|
|
22
|
+
#
|
|
23
|
+
# ## Example
|
|
24
|
+
#
|
|
25
|
+
# If your `_layouts/_banner.erb` looks like this:
|
|
26
|
+
#
|
|
27
|
+
# <div class='banner'>
|
|
28
|
+
# Welcome to <%= start.title %>
|
|
29
|
+
# </div>
|
|
30
|
+
#
|
|
31
|
+
# ...Then this will embed the partial `_layouts/_nav.erb`. The partial
|
|
32
|
+
# will be rendered with `start` being set to the current page.
|
|
33
|
+
#
|
|
34
|
+
# <%= partial '_banner', :start => page %>
|
|
35
|
+
#
|
|
36
|
+
def partial(path, locals={})
|
|
37
|
+
partial = Partial[path.to_s, page] or return ''
|
|
38
|
+
partial.to_html locals.merge(:page => self)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Method: rel (Proton::Helpers)
|
|
42
|
+
# Turns a path into a relative path.
|
|
43
|
+
#
|
|
44
|
+
# ## Usage
|
|
45
|
+
# <%= rel(path) %>
|
|
46
|
+
#
|
|
47
|
+
# ## Description
|
|
48
|
+
# `rel` takes a given absolute path that begins with a `/` (for instance,
|
|
49
|
+
# `/x/y/z.html`) and returns a relative path (maybe `../y/z.html`). This is
|
|
50
|
+
# useful if your site will not be be hosted on it's own domain.
|
|
51
|
+
#
|
|
52
|
+
# ## Example
|
|
53
|
+
# <% page.children.each do |child| %>
|
|
54
|
+
# <a href="<%= rel(child.path) %>">
|
|
55
|
+
# <%= child.title %>
|
|
56
|
+
# </a>
|
|
57
|
+
# <% end %>
|
|
58
|
+
#
|
|
59
|
+
# This may output:
|
|
60
|
+
#
|
|
61
|
+
# <a href="../../foo.html">
|
|
62
|
+
# Foobar
|
|
63
|
+
# </a>
|
|
64
|
+
#
|
|
65
|
+
# ...where the `../../` depends on the current page's path.
|
|
66
|
+
#
|
|
67
|
+
def rel(path)
|
|
68
|
+
depth = page.path.count('/')
|
|
69
|
+
dotdot = depth > 1 ? ('../' * (depth-1)) : './'
|
|
70
|
+
(dotdot[0...-1] + path)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Method: content_for (Proton::Helpers)
|
|
74
|
+
# Content for.
|
|
75
|
+
#
|
|
76
|
+
# ## See also
|
|
77
|
+
#
|
|
78
|
+
# * {Proton::Helpers::has_content?}
|
|
79
|
+
# * {Proton::Helpers::content_for}
|
|
80
|
+
# * {Proton::Helpers::yield_content}
|
|
81
|
+
#
|
|
82
|
+
def content_for(key, &blk)
|
|
83
|
+
content_blocks[key.to_sym] = blk
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def content_blocks
|
|
87
|
+
$content_blocks ||= Hash.new
|
|
88
|
+
$content_blocks[page.path] ||= Hash.new
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Method: has_content? (Proton::Helpers)
|
|
92
|
+
# Checks if there's something defined for a given content block.
|
|
93
|
+
#
|
|
94
|
+
# ## Example
|
|
95
|
+
# See {Proton::Helpers::content_for} for an example.
|
|
96
|
+
#
|
|
97
|
+
# ## See also
|
|
98
|
+
# * {Proton::Helpers::has_content?}
|
|
99
|
+
# * {Proton::Helpers::content_for}
|
|
100
|
+
# * {Proton::Helpers::yield_content}
|
|
101
|
+
#
|
|
102
|
+
def has_content?(key)
|
|
103
|
+
content_blocks.member? key.to_sym
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Method: yield_content (Proton::Helpers)
|
|
107
|
+
# Yield
|
|
108
|
+
#
|
|
109
|
+
# ## Example
|
|
110
|
+
# See {Proton::Helpers::content_for} for an example.
|
|
111
|
+
#
|
|
112
|
+
# ## See also
|
|
113
|
+
# * {Proton::Helpers::has_content?}
|
|
114
|
+
# * {Proton::Helpers::content_for}
|
|
115
|
+
# * {Proton::Helpers::yield_content}
|
|
116
|
+
#
|
|
117
|
+
def yield_content(key, *args)
|
|
118
|
+
content = content_blocks[key.to_sym]
|
|
119
|
+
if respond_to?(:block_is_haml?) && block_is_haml?(content)
|
|
120
|
+
capture_haml(*args, &content)
|
|
121
|
+
elsif content
|
|
122
|
+
content.call(*args)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|