brochure 0.2.0 → 0.3.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/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