brochure 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,9 +1,12 @@
1
1
  Brochure
2
2
  ========
3
3
 
4
- A Rack application for serving static sites with ERB templates (or any
5
- of the many [template languages supported by
4
+ Brochure is a Rack application for serving static sites with ERB
5
+ templates (or any of the many [template languages supported by
6
6
  Tilt](http://github.com/rtomayko/tilt/blob/master/TEMPLATES.md#readme)).
7
+ It's the good parts of PHP wrapped up in a little Ruby package —
8
+ perfect for serving the marketing site for your Rails app.
9
+
7
10
 
8
11
  Sample application structure:
9
12
 
@@ -22,11 +25,11 @@ Sample application structure:
22
25
  Sample `config.ru`:
23
26
 
24
27
  require "brochure"
25
- ROOT = File.dirname(__FILE__)
26
- run Brochure.app(ROOT)
28
+ root = File.dirname(__FILE__)
29
+ run Brochure.app(root)
27
30
 
28
31
 
29
- ## Templates and URL mapping
32
+ ## URL mapping and template rendering
30
33
 
31
34
  URLs are automatically mapped to template names:
32
35
 
@@ -39,10 +42,15 @@ underscore in its filename. So `<%= render "shared/header" %>` will
39
42
  render `templates/shared/_header.html.erb` inline.
40
43
 
41
44
  Templates have access to the Rack environment via the `env` method and
42
- to the Brochure application via the `application` method.
45
+ to the Brochure application via the `application`
46
+ method. Additionally, a `Rack::Request` wrapper around the Rack
47
+ environment is available via the `request` method.
48
+
49
+ You can print HTML-escaped strings in your templates with the `h`
50
+ helper.
43
51
 
44
52
 
45
- ## Helper methods and instance variables
53
+ ## Custom helper methods and instance variables
46
54
 
47
55
  You can make additional helper methods and instance variables
48
56
  available to your templates. Helper methods live in Ruby modules and
@@ -51,21 +59,17 @@ can be included with the `:helpers` option to `Brochure.app`:
51
59
  module AssetHelper
52
60
  def asset_path(filename)
53
61
  local_path = File.join(application.asset_root, filename)
54
- if File.file?(local_path)
55
- cache_buster = "?#{Digest::MD5.hexdigest(IO.read(local_path))}"
56
- else
57
- cache_buster = ""
58
- end
59
- "#{filename}#{cache_buster}"
62
+ digest = Digest::MD5.hexdigest(IO.read(local_path))
63
+ "/#{filename}?#{digest}"
60
64
  end
61
65
  end
62
66
 
63
- run Brochure.app(ROOT, :helpers => [AssetHelper])
67
+ run Brochure.app(root, :helpers => [AssetHelper])
64
68
 
65
69
  Similarly, instance variables can be defined with the `:assigns`
66
70
  option:
67
71
 
68
- run Brochure.app(ROOT, :assigns => { :domain => "37signals.com" })
72
+ run Brochure.app(root, :assigns => { :domain => "37signals.com" })
69
73
 
70
74
 
71
75
  # Installation
data/lib/brochure.rb CHANGED
@@ -3,20 +3,25 @@ require "rack"
3
3
  require "tilt"
4
4
 
5
5
  module Brochure
6
- VERSION = "0.3.1"
6
+ VERSION = "0.4.0"
7
7
 
8
8
  autoload :Application, "brochure/application"
9
9
  autoload :Context, "brochure/context"
10
10
  autoload :Failsafe, "brochure/failsafe"
11
+ autoload :Static, "brochure/static"
12
+ autoload :Template, "brochure/template"
11
13
  autoload :TemplateNotFound, "brochure/errors"
12
14
 
13
15
  def self.app(root, options = {})
14
16
  app = Application.new(root, options)
17
+ app = Static.new(app, app.asset_root)
18
+
15
19
  if development?
16
20
  app = Rack::ShowExceptions.new(app)
17
21
  else
18
22
  app = Failsafe.new(app)
19
23
  end
24
+
20
25
  app
21
26
  end
22
27
 
@@ -47,8 +47,8 @@ module Brochure
47
47
  def call(env)
48
48
  if forbidden?(env["PATH_INFO"])
49
49
  forbidden
50
- elsif template = find_template(env["PATH_INFO"][/[^.]+/])
51
- success render_template(template, env)
50
+ elsif template = find_template(env["PATH_INFO"])
51
+ success template.render(env), template.content_type
52
52
  else
53
53
  not_found(env)
54
54
  end
@@ -58,40 +58,38 @@ module Brochure
58
58
  path[".."] || File.basename(path)[/^_/]
59
59
  end
60
60
 
61
- def find_template(logical_path)
62
- if template_path = find_template_path(logical_path)
61
+ def find_template(logical_path, format_extension = ".html")
62
+ if template_path = find_template_path(logical_path, format_extension)
63
63
  template_for(template_path)
64
64
  end
65
65
  end
66
66
 
67
- def find_partial(logical_path)
68
- if template_path = find_partial_path(logical_path)
67
+ def find_partial(logical_path, format_extension = ".html")
68
+ if template_path = find_partial_path(logical_path, format_extension)
69
69
  template_for(template_path)
70
70
  end
71
71
  end
72
72
 
73
- def find_template_path(logical_path)
74
- candidates = [logical_path + ".html", logical_path + "/index.html"]
75
- template_trail.find(*candidates)
73
+ def find_template_path(logical_path, format_extension)
74
+ template_trail.find(logical_path, logical_path + format_extension, logical_path + "/index" + format_extension)
76
75
  end
77
76
 
78
- def find_partial_path(logical_path)
79
- path_parts = logical_path.split("/")
80
- partial_path = (path_parts[0..-2] + ["_" + path_parts[-1]]).join("/")
81
- template_trail.find(partial_path + ".html")
77
+ def find_partial_path(logical_path, format_extension)
78
+ dirname, basename = File.split(logical_path)
79
+ partial_path = File.join(dirname, "_" + basename)
80
+ template_trail.find(partial_path, partial_path + format_extension)
82
81
  end
83
82
 
84
83
  def template_for(template_path)
85
84
  if Brochure.development?
86
- Tilt.new(template_path)
85
+ Template.new(self, template_path)
87
86
  else
88
- templates[template_path] ||= Tilt.new(template_path)
87
+ templates[template_path] ||= Template.new(self, template_path)
89
88
  end
90
89
  end
91
90
 
92
- def render_template(template, env, locals = {})
93
- context = context_class.new(self, env, assigns)
94
- template.render(context, locals)
91
+ def context_for(template, env)
92
+ context_class.new(self, template, env, assigns)
95
93
  end
96
94
 
97
95
  def respond_with(status, body, content_type = "text/html; charset=utf-8")
@@ -102,13 +100,13 @@ module Brochure
102
100
  [status, headers, [body]]
103
101
  end
104
102
 
105
- def success(body)
106
- respond_with 200, body
103
+ def success(body, content_type)
104
+ respond_with 200, body, content_type
107
105
  end
108
106
 
109
107
  def not_found(env)
110
108
  if template = find_template("404")
111
- respond_with 404, render_template(template, env)
109
+ respond_with 404, template.render(env)
112
110
  else
113
111
  default_not_found
114
112
  end
@@ -8,11 +8,13 @@ module Brochure
8
8
  context
9
9
  end
10
10
 
11
- attr_accessor :application, :env
11
+ attr_reader :application, :template, :env
12
+
13
+ def initialize(application, template, env, assigns = {})
14
+ @application = application
15
+ @template = template
16
+ @env = env
12
17
 
13
- def initialize(application, env, assigns = {})
14
- self.application = application
15
- self.env = env
16
18
  load_assigns(assigns)
17
19
  end
18
20
 
@@ -23,7 +25,7 @@ module Brochure
23
25
  end
24
26
 
25
27
  def request
26
- @_request ||= Rack::Request.new(env)
28
+ @request ||= Rack::Request.new(env)
27
29
  end
28
30
 
29
31
  def h(html)
@@ -31,8 +33,8 @@ module Brochure
31
33
  end
32
34
 
33
35
  def render(logical_path, locals = {})
34
- if template = @application.find_partial(logical_path)
35
- @application.render_template(template, env, locals)
36
+ if partial = application.find_partial(logical_path, template.format_extension)
37
+ partial.render(env, locals)
36
38
  else
37
39
  raise TemplateNotFound, "no such template '#{logical_path}'"
38
40
  end
@@ -0,0 +1,19 @@
1
+ require 'rack/file'
2
+
3
+ module Brochure
4
+ class Static
5
+ def initialize(app, dir)
6
+ @file = Rack::File.new(dir)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ status, headers, body = @file.call(env)
12
+ if status > 400
13
+ @app.call(env)
14
+ else
15
+ [status, headers, body]
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,36 @@
1
+ module Brochure
2
+ class Template
3
+ attr_reader :app, :path
4
+
5
+ def initialize(app, path)
6
+ @app = app
7
+ @path = path
8
+ end
9
+
10
+ def template
11
+ @template ||= Tilt.new(path)
12
+ end
13
+
14
+ def engine_extension
15
+ @engine_extension ||= File.extname(path)
16
+ end
17
+
18
+ def format_extension
19
+ @format_extension ||= begin
20
+ ext = File.extname(File.basename(path, engine_extension))
21
+ ext.empty? ? ".html" : ext
22
+ end
23
+ end
24
+
25
+ def content_type
26
+ @content_type ||= begin
27
+ type = Rack::Mime.mime_type(format_extension)
28
+ type[/^text/] ? "#{type}; charset=utf-8" : type
29
+ end
30
+ end
31
+
32
+ def render(env, locals = {})
33
+ template.render(app.context_for(self, env), locals)
34
+ end
35
+ end
36
+ end
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: 17
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
9
- - 1
10
- version: 0.3.1
8
+ - 4
9
+ - 0
10
+ version: 0.4.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-22 00:00:00 -05:00
19
+ date: 2010-10-27 00:00:00 -05:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -96,6 +96,8 @@ files:
96
96
  - lib/brochure/context.rb
97
97
  - lib/brochure/errors.rb
98
98
  - lib/brochure/failsafe.rb
99
+ - lib/brochure/static.rb
100
+ - lib/brochure/template.rb
99
101
  - lib/brochure.rb
100
102
  - README.md
101
103
  - LICENSE