brochure 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -5,18 +5,14 @@ A Rack application for serving static sites with ERB templates.
5
5
 
6
6
  Sample application structure:
7
7
 
8
- app/
9
- helpers/
10
- analytics_helper.rb
11
- formatting_helper.rb
12
- templates/
13
- help/
14
- index.html.erb
8
+ templates/
9
+ help/
15
10
  index.html.erb
16
- shared/
17
- _header.html.erb
18
- _footer.html.erb
19
- signup.html.erb
11
+ index.html.erb
12
+ shared/
13
+ _header.html.erb
14
+ _footer.html.erb
15
+ signup.html.erb
20
16
  config.ru
21
17
  public/
22
18
  ...
@@ -27,17 +23,13 @@ Sample `config.ru`:
27
23
  run Brochure.app(File.dirname(__FILE__))
28
24
 
29
25
  URLs are automatically mapped to template names. So `/` will render
30
- `app/templates/index.html.erb`, `/signup` will render
31
- `app/templates/signup.html.erb`, `/help/` will render
32
- `app/templates/help/index.html.erb`, and so on.
33
-
34
- Helpers should define a module that maps to their filename. So
35
- `analytics_helper.rb` defines `AnalyticsHelper`,
36
- `html/forms_helper.rb` defines `Html::FormsHelper`, and so on.
26
+ `templates/index.html.erb`, `/signup` will render
27
+ `templates/signup.html.erb`, `/help/` will render
28
+ `templates/help/index.html.erb`, and so on.
37
29
 
38
30
  Templates can render partials. Partials are denoted by a leading
39
31
  underscore in their filename. So `<%= render "shared/header" %>` will
40
- render `app/templates/shared/_header.html.erb` inline.
32
+ render `templates/shared/_header.html.erb` inline.
41
33
 
42
34
  # Installation
43
35
 
@@ -3,15 +3,15 @@ require "rack"
3
3
  require "tilt"
4
4
 
5
5
  module Brochure
6
- VERSION = "0.2.0"
6
+ VERSION = "0.3.0"
7
7
 
8
8
  autoload :Application, "brochure/application"
9
9
  autoload :Context, "brochure/context"
10
10
  autoload :Failsafe, "brochure/failsafe"
11
11
  autoload :TemplateNotFound, "brochure/errors"
12
12
 
13
- def self.app(root)
14
- app = Application.new(root)
13
+ def self.app(root, options = {})
14
+ app = Application.new(root, options)
15
15
  if development?
16
16
  app = Rack::ShowExceptions.new(app)
17
17
  else
@@ -20,10 +20,6 @@ module Brochure
20
20
  app
21
21
  end
22
22
 
23
- def self.camelize(string)
24
- string.gsub(/(^|_)(\w)/) { $2.upcase }
25
- end
26
-
27
23
  def self.development?
28
24
  ENV["RACK_ENV"] == "development"
29
25
  end
@@ -1,27 +1,46 @@
1
1
  module Brochure
2
2
  class Application
3
- attr_reader :app_root, :helper_root, :template_root, :asset_root
3
+ attr_reader :app_root, :template_root, :asset_root, :plugin_root, :assigns
4
4
 
5
- def initialize(root)
6
- @app_root = File.expand_path(root)
7
- @helper_root = File.join(@app_root, "app", "helpers")
8
- @template_root = File.join(@app_root, "app", "templates")
9
- @asset_root = File.join(@app_root, "public")
5
+ def initialize(root, options = {})
6
+ @app_root = File.expand_path(root)
7
+ @template_root = File.join(@app_root, "templates")
8
+ @asset_root = File.join(@app_root, "public")
9
+ @plugin_root = File.join(@app_root, "vendor", "plugins")
10
10
 
11
- @template_trail = Hike::Trail.new(@app_root)
12
- @template_trail.extensions.replace(Tilt.mappings.keys.sort)
13
- @template_trail.paths.push(@template_root)
11
+ @assigns = options[:assigns] || {}
12
+ helpers.push(*options[:helpers]) if options[:helpers]
13
+ initialize_plugins
14
+ end
15
+
16
+ def initialize_plugins
17
+ plugins.each do |plugin_root|
18
+ template_trail.paths.push(File.join(plugin_root, "templates"))
19
+ end
20
+ end
14
21
 
15
- @context_class = Context.for(helpers)
16
- @templates = {}
22
+ def template_trail
23
+ @template_trail ||= Hike::Trail.new(app_root).tap do |trail|
24
+ trail.extensions.replace(Tilt.mappings.keys.sort)
25
+ trail.paths.push(template_root)
26
+ end
27
+ end
28
+
29
+ def context_class
30
+ @context_class ||= Context.for(helpers)
31
+ end
32
+
33
+ def templates
34
+ @templates ||= {}
17
35
  end
18
36
 
19
37
  def helpers
20
- @helpers ||= Dir[File.join(@helper_root, "**", "*.rb")].map do |helper_path|
21
- base_name = helper_path[(@helper_root.length + 1)..-1][/(.*?)\.rb$/, 1]
22
- module_names = base_name.split("/").map { |n| Brochure.camelize(n) }
23
- load helper_path
24
- module_names.inject(Kernel) { |mod, name| mod.const_get(name) }
38
+ @helpers ||= []
39
+ end
40
+
41
+ def plugins
42
+ @plugins ||= Dir[File.join(plugin_root, "*")].select do |entry|
43
+ File.directory?(entry)
25
44
  end
26
45
  end
27
46
 
@@ -31,7 +50,7 @@ module Brochure
31
50
  elsif template = find_template(env["PATH_INFO"][/[^.]+/])
32
51
  success render_template(template, env)
33
52
  else
34
- not_found
53
+ not_found(env)
35
54
  end
36
55
  end
37
56
 
@@ -53,25 +72,25 @@ module Brochure
53
72
 
54
73
  def find_template_path(logical_path)
55
74
  candidates = [logical_path + ".html", logical_path + "/index.html"]
56
- @template_trail.find(*candidates)
75
+ template_trail.find(*candidates)
57
76
  end
58
77
 
59
78
  def find_partial_path(logical_path)
60
79
  path_parts = logical_path.split("/")
61
80
  partial_path = (path_parts[0..-2] + ["_" + path_parts[-1]]).join("/")
62
- @template_trail.find(partial_path + ".html")
81
+ template_trail.find(partial_path + ".html")
63
82
  end
64
83
 
65
84
  def template_for(template_path)
66
85
  if Brochure.development?
67
86
  Tilt.new(template_path)
68
87
  else
69
- @templates[template_path] ||= Tilt.new(template_path)
88
+ templates[template_path] ||= Tilt.new(template_path)
70
89
  end
71
90
  end
72
91
 
73
92
  def render_template(template, env, locals = {})
74
- context = @context_class.new(self, env)
93
+ context = context_class.new(self, env, assigns)
75
94
  template.render(context, locals)
76
95
  end
77
96
 
@@ -87,7 +106,15 @@ module Brochure
87
106
  respond_with 200, body
88
107
  end
89
108
 
90
- def not_found
109
+ def not_found(env)
110
+ if template = find_template("404")
111
+ respond_with 404, render_template(template, env)
112
+ else
113
+ default_not_found
114
+ end
115
+ end
116
+
117
+ def default_not_found
91
118
  respond_with 404, <<-HTML
92
119
  <!DOCTYPE html>
93
120
  <html><head><title>Not Found</title></head>
@@ -10,15 +10,26 @@ module Brochure
10
10
 
11
11
  attr_accessor :application, :env
12
12
 
13
- def initialize(application, env)
13
+ def initialize(application, env, assigns = {})
14
14
  self.application = application
15
15
  self.env = env
16
+ load_assigns(assigns)
17
+ end
18
+
19
+ def load_assigns(assigns)
20
+ assigns.each do |name, value|
21
+ instance_variable_set("@#{name}", value)
22
+ end
16
23
  end
17
24
 
18
25
  def request
19
26
  @_request ||= Rack::Request.new(env)
20
27
  end
21
28
 
29
+ def h(html)
30
+ Rack::Utils.escape_html(html)
31
+ end
32
+
22
33
  def render(logical_path, locals = {})
23
34
  if template = @application.find_partial(logical_path)
24
35
  @application.render_template(template, env, locals)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brochure
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 0.2.0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sam Stephenson
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-10-16 00:00:00 -05:00
19
+ date: 2010-10-21 00:00:00 -05:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency