proton 0.3.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|