mango 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -2
- data/.rvmrc +1 -0
- data/.yardopts +1 -3
- data/{CHANGES.mdown → CHANGES.md} +40 -0
- data/Gemfile.lock +35 -23
- data/LICENSE +1 -1
- data/{README.mdown → README.md} +38 -27
- data/Rakefile +0 -13
- data/lib/mango.rb +5 -0
- data/lib/mango/application.rb +361 -129
- data/lib/mango/content_page.rb +89 -115
- data/lib/mango/core_ext/string.rb +16 -0
- data/lib/mango/core_ext/uri.rb +14 -0
- data/lib/mango/dependencies.rb +5 -4
- data/lib/mango/flavored_markdown.rb +7 -0
- data/lib/mango/rack/debugger.rb +20 -0
- data/lib/mango/runner.rb +33 -50
- data/lib/mango/templates/.gitignore +0 -1
- data/lib/mango/templates/Gemfile +1 -1
- data/lib/mango/templates/content/index.erb +6 -0
- data/lib/mango/templates/themes/default/javascripts/timer.coffee +6 -0
- data/lib/mango/templates/themes/default/public/javascripts/fireworks.js +0 -0
- data/lib/mango/templates/themes/default/public/{styles → stylesheets}/fireworks.css +0 -0
- data/lib/mango/templates/themes/default/public/{styles → stylesheets}/reset.css +0 -2
- data/lib/mango/templates/themes/default/{styles → stylesheets}/screen.sass +0 -2
- data/lib/mango/templates/themes/default/views/layout.haml +5 -5
- data/lib/mango/templates/themes/default/views/page.haml +1 -3
- data/lib/mango/version.rb +1 -1
- data/mango.gemspec +12 -10
- data/spec/fixture/content/engines/erb.erb +7 -0
- data/spec/fixture/content/engines/haml.haml +4 -4
- data/spec/fixture/content/engines/liquid.liquid +7 -0
- data/spec/fixture/content/engines/markdown.markdown +0 -6
- data/spec/fixture/content/engines/md.md +0 -6
- data/spec/fixture/content/engines/mkd.mkd +1 -0
- data/spec/fixture/content/page_with_missing_view.haml +2 -2
- data/spec/fixture/content/page_with_unregistered_view.haml +4 -0
- data/spec/fixture/content/view_engines/erb.haml +4 -0
- data/spec/fixture/content/view_engines/liquid.haml +4 -0
- data/spec/fixture/themes/default/javascripts/override.coffee +1 -0
- data/spec/fixture/themes/default/javascripts/siblings.coffee +7 -0
- data/spec/fixture/themes/default/javascripts/songs/happy.coffee +5 -0
- data/spec/fixture/themes/default/public/404.html +11 -0
- data/spec/fixture/themes/default/public/javascripts/econ.js +8 -0
- data/spec/fixture/themes/default/public/javascripts/math/opposite.js +6 -0
- data/spec/fixture/themes/default/public/javascripts/override.js +1 -0
- data/spec/fixture/themes/default/public/root.js +5 -0
- data/spec/fixture/themes/default/public/{styles → stylesheets}/override.css +0 -0
- data/spec/fixture/themes/default/public/{styles → stylesheets}/reset.css +0 -0
- data/spec/fixture/themes/default/public/{styles → stylesheets}/subfolder/another.css +0 -0
- data/spec/fixture/themes/default/security_hole.js +1 -0
- data/spec/fixture/themes/default/{styles → stylesheets}/override.sass +0 -0
- data/spec/fixture/themes/default/{styles/screen.sass → stylesheets/sass.sass} +4 -2
- data/spec/fixture/themes/default/stylesheets/scss.scss +19 -0
- data/spec/fixture/themes/default/{styles → stylesheets}/subfolder/screen.sass +0 -2
- data/spec/fixture/themes/default/views/404.erb +11 -0
- data/spec/fixture/themes/default/views/404.haml +1 -0
- data/spec/fixture/themes/default/views/404.liquid +11 -0
- data/spec/fixture/themes/default/views/layout.erb +10 -0
- data/spec/fixture/themes/default/views/layout.haml +1 -1
- data/spec/fixture/themes/default/views/layout.liquid +10 -0
- data/spec/fixture/themes/default/views/page.erb +7 -0
- data/spec/fixture/themes/default/views/page.haml +3 -1
- data/spec/fixture/themes/default/views/page.liquid +7 -0
- data/spec/lib/application/routing_content_pages_spec.rb +298 -21
- data/spec/lib/application/routing_javascript_templates_spec.rb +278 -0
- data/spec/lib/application/routing_not_found_spec.rb +254 -0
- data/spec/lib/application/routing_public_files_spec.rb +9 -8
- data/spec/lib/application/{routing_style_sheets_spec.rb → routing_stylesheet_templates_spec.rb} +61 -24
- data/spec/lib/application_spec.rb +31 -2
- data/spec/lib/content_page/initializing_spec.rb +399 -126
- data/spec/lib/content_page_spec.rb +23 -19
- data/spec/lib/core_ext/string_spec.rb +12 -0
- data/spec/lib/core_ext/uri_spec.rb +42 -0
- data/spec/lib/dependencies_spec.rb +0 -1
- data/spec/lib/flavored_markdown_spec.rb +18 -3
- data/spec/lib/runner_spec.rb +40 -39
- data/spec/lib/version_spec.rb +4 -4
- metadata +145 -64
- data/lib/mango/templates/content/index.md +0 -5
- data/lib/mango/templates/themes/default/public/javascripts/timer.js +0 -5
- data/spec/fixture/content/engines/mdown.mdown +0 -7
- data/spec/lib/content_page/finding_spec.rb +0 -213
data/.gitignore
CHANGED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm ruby-1.9.2-p180@mango
|
data/.yardopts
CHANGED
@@ -1,5 +1,45 @@
|
|
1
1
|
# CHANGES
|
2
2
|
|
3
|
+
## v0.6.0 / 2011-05-29
|
4
|
+
|
5
|
+
[Full changes](https://github.com/ryansobol/mango/compare/v0.5.4...v0.6.0)
|
6
|
+
|
7
|
+
## Features
|
8
|
+
|
9
|
+
* Add ERB view template support [GH#21](https://github.com/ryansobol/mango/issues/21)
|
10
|
+
* Add ERB 404 template support [GH#26](https://github.com/ryansobol/mango/issues/26)
|
11
|
+
* Add 404 default response [GH#27](https://github.com/ryansobol/mango/issues/27)
|
12
|
+
* Add 404.html public file support [GH#28](https://github.com/ryansobol/mango/issues/28)
|
13
|
+
* Add Scss stylesheet template support [GH#31](https://github.com/ryansobol/mango/issues/31)
|
14
|
+
* Add ERB content page support [GH#33](https://github.com/ryansobol/mango/issues/33)
|
15
|
+
* Use ContentPage as local `page` variable within content page and view templates [GH#34](https://github.com/ryansobol/mango/issues/34)
|
16
|
+
* Add Liquid content page, view template, and 404 template support [GH#40](https://github.com/ryansobol/mango/issues/40)
|
17
|
+
* Add CoffeeScript support and JavaScript route handler [GH#36](https://github.com/ryansobol/mango/issues/36)
|
18
|
+
|
19
|
+
### Dependencies
|
20
|
+
|
21
|
+
* Update Sinatra to ~> 1.2.6 [GH#14](https://github.com/ryansobol/mango/issues/14)
|
22
|
+
* Update RSpec to ~> 2.6.0 [GH#32](https://github.com/ryansobol/mango/issues/32)
|
23
|
+
* Add Sass ~> 3.1.1 [GH#24](https://github.com/ryansobol/mango/issues/24)
|
24
|
+
* Update Haml to ~> 3.1.1 [GH#23](https://github.com/ryansobol/mango/issues/23)
|
25
|
+
* Update Rack::Test to ~> 0.6.0 [GH#25](https://github.com/ryansobol/mango/issues/25)
|
26
|
+
* Update YARD to ~> 0.7.1 [GH#38](https://github.com/ryansobol/mango/issues/38)
|
27
|
+
|
28
|
+
### Chores
|
29
|
+
|
30
|
+
* Unignore .rvmrc [GH#16](https://github.com/ryansobol/mango/issues/16)
|
31
|
+
* Move `Mango::Application#directory_path?` to `URI.directory?` [GH#29](https://github.com/ryansobol/mango/issues/29)
|
32
|
+
* Move `File.templatize` to `String#templatize` and simplify usage [GH#30](https://github.com/ryansobol/mango/issues/30)
|
33
|
+
* Rename all `.mdown` files to `.md` [GH#37](https://github.com/ryansobol/mango/issues/37)
|
34
|
+
* Remove the `yard` task from the Rakefile [GH#6](https://github.com/ryansobol/mango/issues/6)
|
35
|
+
* Add spec coverage for 404.liquid route handling [GH#42](https://github.com/ryansobol/mango/issues/42)
|
36
|
+
* Update rspec-core to 2.6.2 [GH#41](https://github.com/ryansobol/mango/issues/41)
|
37
|
+
* Update tilt to 1.3.1 [GH#43](https://github.com/ryansobol/mango/issues/43)
|
38
|
+
* Update LICENSE copyright to 2011 [GH#47](https://github.com/ryansobol/mango/issues/47)
|
39
|
+
* Update rspec-core to 2.6.3 [GH#46](https://github.com/ryansobol/mango/issues/46)
|
40
|
+
* Update Tilt to 1.3.2 [GH#45](https://github.com/ryansobol/mango/issues/45)
|
41
|
+
* Update multi_json to 1.0.3 [GH#53](https://github.com/ryansobol/mango/issues/53)
|
42
|
+
|
3
43
|
## v0.5.4 / 2011-04-24
|
4
44
|
|
5
45
|
[Full changes](https://github.com/ryansobol/mango/compare/v0.5.3...v0.5.4)
|
data/Gemfile.lock
CHANGED
@@ -1,39 +1,49 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
mango (0.
|
4
|
+
mango (0.6.0)
|
5
5
|
bluecloth (~> 2.1.0)
|
6
6
|
bundler (~> 1.0.7)
|
7
|
-
|
7
|
+
coffee-script (~> 2.2.0)
|
8
|
+
haml (~> 3.1.1)
|
9
|
+
liquid (~> 2.2.2)
|
8
10
|
rack (~> 1.2.2)
|
9
|
-
|
11
|
+
sass (~> 3.1.1)
|
12
|
+
sinatra (~> 1.2.6)
|
10
13
|
thor (~> 0.14.6)
|
11
14
|
|
12
15
|
GEM
|
13
16
|
remote: http://rubygems.org/
|
14
17
|
specs:
|
15
18
|
bluecloth (2.1.0)
|
19
|
+
coffee-script (2.2.0)
|
20
|
+
coffee-script-source
|
21
|
+
execjs
|
22
|
+
coffee-script-source (1.1.1)
|
16
23
|
diff-lcs (1.1.2)
|
17
|
-
|
24
|
+
execjs (1.0.0)
|
25
|
+
multi_json (~> 1.0)
|
26
|
+
haml (3.1.1)
|
27
|
+
liquid (2.2.2)
|
28
|
+
multi_json (1.0.3)
|
18
29
|
rack (1.2.2)
|
19
|
-
rack-test (0.
|
30
|
+
rack-test (0.6.0)
|
20
31
|
rack (>= 1.0)
|
21
|
-
rspec (2.
|
22
|
-
rspec-core (~> 2.
|
23
|
-
rspec-expectations (~> 2.
|
24
|
-
rspec-mocks (~> 2.
|
25
|
-
rspec-core (2.
|
26
|
-
rspec-expectations (2.
|
32
|
+
rspec (2.6.0)
|
33
|
+
rspec-core (~> 2.6.0)
|
34
|
+
rspec-expectations (~> 2.6.0)
|
35
|
+
rspec-mocks (~> 2.6.0)
|
36
|
+
rspec-core (2.6.3)
|
37
|
+
rspec-expectations (2.6.0)
|
27
38
|
diff-lcs (~> 1.1.2)
|
28
|
-
rspec-mocks (2.
|
29
|
-
|
39
|
+
rspec-mocks (2.6.0)
|
40
|
+
sass (3.1.1)
|
41
|
+
sinatra (1.2.6)
|
30
42
|
rack (~> 1.1)
|
31
43
|
tilt (>= 1.2.2, < 2.0)
|
32
44
|
thor (0.14.6)
|
33
|
-
tilt (1.
|
34
|
-
yard (0.
|
35
|
-
yard-sinatra (0.5.1)
|
36
|
-
yard (~> 0.6.0)
|
45
|
+
tilt (1.3.2)
|
46
|
+
yard (0.7.1)
|
37
47
|
|
38
48
|
PLATFORMS
|
39
49
|
ruby
|
@@ -41,12 +51,14 @@ PLATFORMS
|
|
41
51
|
DEPENDENCIES
|
42
52
|
bluecloth (~> 2.1.0)
|
43
53
|
bundler (~> 1.0.7)
|
44
|
-
|
54
|
+
coffee-script (~> 2.2.0)
|
55
|
+
haml (~> 3.1.1)
|
56
|
+
liquid (~> 2.2.2)
|
45
57
|
mango!
|
46
58
|
rack (~> 1.2.2)
|
47
|
-
rack-test (~> 0.
|
48
|
-
rspec (~> 2.
|
49
|
-
|
59
|
+
rack-test (~> 0.6.0)
|
60
|
+
rspec (~> 2.6.0)
|
61
|
+
sass (~> 3.1.1)
|
62
|
+
sinatra (~> 1.2.6)
|
50
63
|
thor (~> 0.14.6)
|
51
|
-
yard (~> 0.
|
52
|
-
yard-sinatra (~> 0.5.1)
|
64
|
+
yard (~> 0.7.1)
|
data/LICENSE
CHANGED
data/{README.mdown → README.md}
RENAMED
@@ -1,5 +1,5 @@
|
|
1
|
-
Mango release 0.
|
2
|
-
|
1
|
+
Mango release 0.6.0 (May 29, 2011)
|
2
|
+
==================================
|
3
3
|
|
4
4
|
Copyright (c) 2010 Ryan Sobol. Licensed under the MIT license. Please see the {file:LICENSE} for more information.
|
5
5
|
|
@@ -27,17 +27,26 @@ Mango integrates with the writing tools you're already familiar with -- the file
|
|
27
27
|
|
28
28
|
Working with a text editor you already know *saves time*. And writing and revising content in a file *is often easier* then using the clunky administrator interface of a CMS (e.g. WordPress). Plus, files *match perfectly* with version control systems, like [Git](http://git-scm.com/), for powerful revision history. Bonus!
|
29
29
|
|
30
|
+
Mango supports the following *easy to write* content formats:
|
31
|
+
|
32
|
+
* [Markdown](http://daringfireball.net/projects/markdown/basics)
|
33
|
+
* [Haml](http://haml-lang.com/tutorial.html)
|
34
|
+
* [ERB](http://ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html)
|
35
|
+
* [Liquid](https://github.com/tobi/liquid/wiki)
|
36
|
+
|
37
|
+
Don't see your favorite content format? [Patches are welcomed](https://github.com/ryansobol/mango/issues)
|
38
|
+
|
30
39
|
### Easy to theme
|
31
40
|
|
32
|
-
Mango separates a website's theme from it's content. This makes it *easy to change* the look-and-feel of a single page or an entire website. Mango also supports powerful template languages that make it *easy to have uniformity* with major sections (i.e. headers, footers, navigation, sidebars, etc.) across multiple pages.
|
41
|
+
Mango separates a website's theme from it's content. This makes it *easy to change* the look-and-feel of a single page or an entire website. Mango also supports powerful template languages that make it *easy to have uniformity* with major sections (i.e. headers, footers, navigation, sidebars, etc.) across multiple pages. In addition to the standard browser formats -- HTML, CSS, and JavaScript -- Mango also supports the following template engines:
|
33
42
|
|
34
|
-
*
|
35
|
-
*
|
36
|
-
*
|
37
|
-
*
|
38
|
-
*
|
43
|
+
* [Haml](http://haml-lang.com/)
|
44
|
+
* [ERB](http://ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html)
|
45
|
+
* [Liquid](https://github.com/tobi/liquid/wiki)
|
46
|
+
* [Scss](http://sass-lang.com/) and [Sass](http://sass-lang.com/)
|
47
|
+
* [CoffeeScript](http://jashkenas.github.com/coffee-script/)
|
39
48
|
|
40
|
-
|
49
|
+
Don't see your favorite template engine? [Patches are welcomed](https://github.com/ryansobol/mango/issues)
|
41
50
|
|
42
51
|
### Easy to publish
|
43
52
|
|
@@ -53,7 +62,7 @@ With a strong separation of writing, theming and publishing, Mango applications
|
|
53
62
|
|
54
63
|
### Easy to maintain
|
55
64
|
|
56
|
-
Mango is a database-less web framework. With no database to install, configure, or manage, the maintenance needed to keep your website in working order is *drastically reduced*. And because Mango is distributed as a RubyGem and respects [Semantic Versioning](http://semver.org/), *upgrading is painless
|
65
|
+
Mango is a database-less web framework. With no database to install, configure, or manage, the maintenance needed to keep your website in working order is *drastically reduced*. And because Mango is distributed as a RubyGem and respects [Semantic Versioning](http://semver.org/), *upgrading is painless and backwards-compatible* between patch releases.
|
57
66
|
|
58
67
|
### Easy to scale
|
59
68
|
|
@@ -74,18 +83,20 @@ REQUIREMENTS
|
|
74
83
|
* [RubyGems](https://rubygems.org/) >= 1.3.7 (bundled with Ruby)
|
75
84
|
* [Bundler](http://gembundler.com/) ~> 1.0.7
|
76
85
|
* [Rack](http://rack.rubyforge.org/) ~> 1.2.2
|
77
|
-
* [Sinatra](http://www.sinatrarb.com/) ~> 1.
|
78
|
-
* [Haml](http://haml-lang.com/) ~> 3.
|
79
|
-
* [Sass](http://sass-lang.com/) ~> 3.
|
86
|
+
* [Sinatra](http://www.sinatrarb.com/) ~> 1.2.6
|
87
|
+
* [Haml](http://haml-lang.com/) ~> 3.1.1
|
88
|
+
* [Sass](http://sass-lang.com/) ~> 3.1.1
|
80
89
|
* [BlueCloth](http://deveiate.org/projects/BlueCloth) ~> 2.1.0
|
90
|
+
* [Liquid](http://www.liquidmarkup.org/) ~> 2.2.2
|
91
|
+
* [CoffeeScript](http://jashkenas.github.com/coffee-script/) ~> 2.2.0
|
81
92
|
* [Thor](https://github.com/wycats/thor) ~> 0.14.6
|
82
93
|
|
83
94
|
### Optional development dependencies
|
84
95
|
|
85
96
|
* [Rake](http://rake.rubyforge.org/) ~> 0.8.7 (bundled with Ruby)
|
86
|
-
* [Rack::Test](https://github.com/brynary/rack-test) ~> 0.
|
87
|
-
* [RSpec](http://rspec.info/) ~> 2.
|
88
|
-
* [YARD](http://yardoc.org/) ~> 0.
|
97
|
+
* [Rack::Test](https://github.com/brynary/rack-test) ~> 0.6.0
|
98
|
+
* [RSpec](http://rspec.info/) ~> 2.6.0
|
99
|
+
* [YARD](http://yardoc.org/) ~> 0.7.1
|
89
100
|
* [YARD::Sinatra](https://github.com/rkh/yard-sinatra) ~> 0.5.1
|
90
101
|
* [BlueCloth](http://deveiate.org/projects/BlueCloth) ~> 2.1.0
|
91
102
|
|
@@ -117,7 +128,7 @@ Simply edit the gem version in your application's `Gemfile` and re-install with
|
|
117
128
|
$ cat Gemfile
|
118
129
|
# encoding: UTF-8
|
119
130
|
source "http://rubygems.org"
|
120
|
-
gem "mango", "~> 0.
|
131
|
+
gem "mango", "~> 0.6.0"
|
121
132
|
$ bundle install
|
122
133
|
|
123
134
|
**TIP:** If you're working in the insolation of an [RVM gemset](http://rvm.beginrescueend.com/gemsets/basics/), type `gem clean` to uninstall outdated gems.
|
@@ -166,21 +177,22 @@ Now that the newly generated Mango application is running, here's how the applic
|
|
166
177
|
├── README.md
|
167
178
|
├── config.ru
|
168
179
|
├── content
|
169
|
-
│ └── index.
|
180
|
+
│ └── index.erb
|
170
181
|
└── themes
|
171
182
|
└── default
|
183
|
+
├── javascripts
|
184
|
+
│ └── timer.coffee
|
172
185
|
├── public
|
173
186
|
│ ├── favicon.ico
|
174
187
|
│ ├── images
|
175
188
|
│ │ └── particles.gif
|
176
189
|
│ ├── javascripts
|
177
|
-
│ │
|
178
|
-
│ │ └── timer.js
|
190
|
+
│ │ └── fireworks.js
|
179
191
|
│ ├── robots.txt
|
180
|
-
│ └──
|
192
|
+
│ └── stylesheets
|
181
193
|
│ ├── fireworks.css
|
182
194
|
│ └── reset.css
|
183
|
-
├──
|
195
|
+
├── stylesheets
|
184
196
|
│ └── screen.sass
|
185
197
|
└── views
|
186
198
|
├── 404.haml
|
@@ -193,11 +205,10 @@ Now that the newly generated Mango application is running, here's how the applic
|
|
193
205
|
|
194
206
|
* First, Mango tries to route an HTTP request to a static file found in `themes/default/public/`.
|
195
207
|
* If no static file is found, Mango tries to route the request to a template file.
|
196
|
-
* For routes ending in `.
|
197
|
-
* For
|
198
|
-
|
199
|
-
|
200
|
-
* If no static or template file is found, Mango routes unknown HTTP requests to a customizable 404 page found in `themes/default/views`.
|
208
|
+
* For routes ending in `.js`, Mango searches for a stylesheet template in `themes/javascripts/`.
|
209
|
+
* For routes ending in `.css`, Mango searches for a stylesheet template in `themes/stylesheets/`.
|
210
|
+
* For all other routes, Mango searches for a content page in `content/` and wraps it within a view template in `themes/default/views`.
|
211
|
+
* If no static or template file is found, Mango routes unknown HTTP requests to a customizable 404 page found in either `themes/default/public` or `themes/default/views`.
|
201
212
|
|
202
213
|
WRITING
|
203
214
|
-------
|
data/Rakefile
CHANGED
@@ -15,19 +15,6 @@ end
|
|
15
15
|
|
16
16
|
###################################################################################################
|
17
17
|
|
18
|
-
begin
|
19
|
-
require "yard"
|
20
|
-
require "bluecloth" # for Markdown support
|
21
|
-
require "yard/sinatra" # for Sinatra support
|
22
|
-
YARD::Rake::YardocTask.new(:yard) do |t|
|
23
|
-
t.options += ["--title", "Mango #{Mango::VERSION} Documentation"]
|
24
|
-
end
|
25
|
-
rescue LoadError => e
|
26
|
-
Mango::Dependencies.create_warning_for(e)
|
27
|
-
end
|
28
|
-
|
29
|
-
###################################################################################################
|
30
|
-
|
31
18
|
namespace :gem do
|
32
19
|
desc "Builds a gem from the current project's Gem::Specification"
|
33
20
|
task :build do
|
data/lib/mango.rb
CHANGED
@@ -4,7 +4,12 @@
|
|
4
4
|
require File.expand_path("mango/dependencies", File.dirname(__FILE__))
|
5
5
|
|
6
6
|
require_relative "mango/version"
|
7
|
+
require_relative "mango/core_ext/string"
|
8
|
+
require_relative "mango/core_ext/uri"
|
7
9
|
require_relative "mango/rack/debugger"
|
8
10
|
require_relative "mango/application"
|
9
11
|
require_relative "mango/flavored_markdown"
|
10
12
|
require_relative "mango/content_page"
|
13
|
+
|
14
|
+
# @see http://en.wikipedia.org/wiki/Mango
|
15
|
+
module Mango; end
|
data/lib/mango/application.rb
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
require "sinatra/base"
|
3
3
|
require "haml"
|
4
4
|
require "sass"
|
5
|
+
require "erb"
|
6
|
+
require "liquid"
|
7
|
+
require "bluecloth"
|
8
|
+
require "coffee_script"
|
5
9
|
|
6
10
|
module Mango
|
7
11
|
# It's probably no surprise that `Mango::Application` is a modular **application controller**
|
@@ -12,10 +16,11 @@ module Mango
|
|
12
16
|
# For **every HTTP request**, the application will first attempt to match the request URI path to
|
13
17
|
# a public file found within `settings.public` and send that file with a 200 response code.
|
14
18
|
#
|
15
|
-
# In addition to serving static assets, the application has
|
19
|
+
# In addition to serving static assets, the application has these dynamic route handlers:
|
16
20
|
#
|
17
21
|
# * Content page templates with `GET *`
|
18
|
-
# *
|
22
|
+
# * JavaScript templates with `GET /javascripts/*.js`
|
23
|
+
# * Stylesheet templates with `GET /stylesheets/*.css`
|
19
24
|
#
|
20
25
|
# and one error handler:
|
21
26
|
#
|
@@ -23,7 +28,7 @@ module Mango
|
|
23
28
|
#
|
24
29
|
# # Serving public files found within `settings.public`
|
25
30
|
#
|
26
|
-
# ### Example requests routed to public files
|
31
|
+
# ### Example requests routed to public files
|
27
32
|
#
|
28
33
|
# |-- content
|
29
34
|
# | `-- override.haml
|
@@ -47,86 +52,199 @@ module Mango
|
|
47
52
|
#
|
48
53
|
# # Content page templates with `GET *`
|
49
54
|
#
|
50
|
-
# ### Example `GET *` requests routed to content
|
55
|
+
# ### Example `GET *` requests routed to content page templates
|
51
56
|
#
|
52
57
|
# |-- content
|
53
58
|
# | |-- about
|
54
|
-
# | | |-- index.
|
59
|
+
# | | |-- index.erb
|
55
60
|
# | | `-- us.haml
|
56
|
-
# | |-- index.
|
61
|
+
# | |-- index.markdown
|
57
62
|
# | |-- override.haml
|
58
63
|
# | `-- turner+hooch.haml
|
59
64
|
# `-- security_hole.haml
|
60
65
|
#
|
61
|
-
# GET / => 200 content/index.
|
62
|
-
# GET /index => 200 content/index.
|
63
|
-
# GET /index?foo=bar => 200 content/index.
|
64
|
-
# GET /about/ => 200 content/about/index.
|
65
|
-
# GET /about/index => 200 content/about/index.
|
66
|
+
# GET / => 200 content/index.markdown
|
67
|
+
# GET /index => 200 content/index.markdown
|
68
|
+
# GET /index?foo=bar => 200 content/index.markdown
|
69
|
+
# GET /about/ => 200 content/about/index.erb
|
70
|
+
# GET /about/index => 200 content/about/index.erb
|
66
71
|
# GET /about/us => 200 content/about/us.haml
|
67
72
|
# GET /turner%2Bhooch => 200 content/turner+hooch.haml
|
68
73
|
#
|
69
74
|
# GET /page_not_found => pass to NOT_FOUND error handler
|
70
75
|
# GET /../security_hole => pass to NOT_FOUND error handler
|
71
76
|
#
|
72
|
-
# #
|
77
|
+
# # JavaScript templates with `GET /javascripts/*.js`
|
73
78
|
#
|
74
|
-
# ### Example `GET /
|
79
|
+
# ### Example `GET /javascripts/*.js` requests routed to JavaScript files and templates
|
80
|
+
#
|
81
|
+
# `-- themes
|
82
|
+
# `-- default
|
83
|
+
# |-- javascripts
|
84
|
+
# | |-- override.coffee
|
85
|
+
# | |-- siblings.coffee
|
86
|
+
# | `-- songs
|
87
|
+
# | `-- happy.coffee
|
88
|
+
# |-- public
|
89
|
+
# | |-- root.js
|
90
|
+
# | `-- stylesheets
|
91
|
+
# | |-- econ.js
|
92
|
+
# | |-- math
|
93
|
+
# | | `-- opposite.js
|
94
|
+
# | `-- override.js
|
95
|
+
# `-- security_hole.js
|
96
|
+
#
|
97
|
+
# GET /javascripts/siblings.js => 200 themes/default/stylesheets/siblings.coffee
|
98
|
+
# GET /javascripts/songs/happy.js => 200 themes/default/stylesheets/songs/happy.coffee
|
99
|
+
#
|
100
|
+
# GET /javascripts/econ.js => 200 themes/default/public/javascripts/econ.js
|
101
|
+
# GET /javascripts/override.js => 200 themes/default/public/javascripts/override.js
|
102
|
+
# GET /root.js => 200 themes/default/public/root.js
|
103
|
+
# GET /javascripts/math/opposite.js => 200 themes/default/public/javascripts/math/opposite.js
|
104
|
+
#
|
105
|
+
# GET /javascripts/not_found.js => pass to NOT_FOUND error handler
|
106
|
+
# GET /siblings.js => pass to NOT_FOUND error handler
|
107
|
+
# GET /javascripts/../security_hole.js => pass to NOT_FOUND error handler
|
108
|
+
#
|
109
|
+
# # Stylesheet templates with `GET /stylesheets/*.css`
|
110
|
+
#
|
111
|
+
# ### Example `GET /stylesheets/*.css` requests routed to stylesheets files and templates
|
75
112
|
#
|
76
113
|
# `-- themes
|
77
114
|
# `-- default
|
78
115
|
# |-- public
|
79
116
|
# | |-- default.css
|
80
|
-
# | `--
|
117
|
+
# | `-- stylesheets
|
81
118
|
# | |-- override.css
|
82
119
|
# | |-- reset.css
|
83
|
-
# | `--
|
84
|
-
# | `--
|
120
|
+
# | `-- folder
|
121
|
+
# | `-- print.css
|
85
122
|
# |-- security_hole.sass
|
86
|
-
# `--
|
123
|
+
# `-- stylesheets
|
87
124
|
# |-- override.sass
|
88
|
-
# |-- screen.
|
89
|
-
# `--
|
90
|
-
# `--
|
125
|
+
# |-- screen.scss
|
126
|
+
# `-- folder
|
127
|
+
# `-- mobile.sass
|
91
128
|
#
|
92
|
-
# GET /
|
93
|
-
# GET /
|
129
|
+
# GET /stylesheets/screen.css => 200 themes/default/stylesheets/screen.scss
|
130
|
+
# GET /stylesheets/folder/mobile.css => 200 themes/default/stylesheets/folder/mobile.sass
|
94
131
|
#
|
95
|
-
# GET /
|
96
|
-
# GET /
|
132
|
+
# GET /stylesheets/reset.css => 200 themes/default/public/stylesheets/reset.css
|
133
|
+
# GET /stylesheets/override.css => 200 themes/default/public/stylesheets/override.css
|
97
134
|
# GET /default.css => 200 themes/default/public/default.css
|
98
|
-
# GET /
|
135
|
+
# GET /stylesheets/folder/print.css => 200 themes/default/public/stylesheets/folder/print.css
|
99
136
|
#
|
100
|
-
# GET /
|
101
|
-
# GET /screen.css
|
102
|
-
# GET /
|
137
|
+
# GET /stylesheets/not_found.css => pass to NOT_FOUND error handler
|
138
|
+
# GET /screen.css => pass to NOT_FOUND error handler
|
139
|
+
# GET /stylesheets/../security_hole.css => pass to NOT_FOUND error handler
|
103
140
|
#
|
104
141
|
# # 404 Page Not Found with `NOT_FOUND`
|
105
142
|
#
|
106
143
|
# When a requested URI path cannot be matched with a public file or template file, the error
|
107
|
-
# handler
|
144
|
+
# handler attempts to send a 404 public file or a rendered a 404 template with a 404 HTTP
|
145
|
+
# response.
|
146
|
+
#
|
147
|
+
# ### Example `GET /page_not_found` request routed to a 404 public file
|
148
|
+
#
|
149
|
+
# `-- themes
|
150
|
+
# `-- default
|
151
|
+
# `-- public
|
152
|
+
# `-- 404.html
|
153
|
+
#
|
154
|
+
# GET /page_not_found => 404 themes/default/public/404.html
|
155
|
+
#
|
156
|
+
# ### Example `GET /page_not_found` request routed to a 404 Haml template
|
157
|
+
#
|
158
|
+
# |-- content
|
159
|
+
# | `-- index.haml
|
160
|
+
# `-- themes
|
161
|
+
# `-- default
|
162
|
+
# `-- views
|
163
|
+
# `-- 404.haml
|
164
|
+
#
|
165
|
+
# GET /page_not_found => 404 themes/default/views/404.haml
|
166
|
+
#
|
167
|
+
# If no 404 public file or template is found, the application sends a basic "Page Not Found" page
|
168
|
+
# with a 404 HTTP response.
|
108
169
|
#
|
109
170
|
class Application < Sinatra::Base
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
set :
|
171
|
+
# @macro [attach] sinatra.set
|
172
|
+
# Defines `settings.$1`
|
173
|
+
# @attribute
|
174
|
+
# @overload $*
|
175
|
+
# @return [String]
|
176
|
+
set :root, Dir.getwd
|
177
|
+
set :theme, "default"
|
178
|
+
set :javascripts, lambda { File.join(root, "themes", theme, "javascripts") }
|
179
|
+
set :public, lambda { File.join(root, "themes", theme, "public") }
|
180
|
+
set :stylesheets, lambda { File.join(root, "themes", theme, "stylesheets") }
|
181
|
+
set :views, lambda { File.join(root, "themes", theme, "views") }
|
182
|
+
set :content, lambda { File.join(root, "content") }
|
183
|
+
|
184
|
+
# @macro [attach] sinatra.mime_type
|
185
|
+
# Registers `$2` as the mime type for static files ending with `$1`
|
186
|
+
# @scope class
|
187
|
+
# @attribute
|
188
|
+
# @overload $*
|
189
|
+
# @return [String]
|
190
|
+
mime_type "", "text/html"
|
116
191
|
|
192
|
+
# @macro [attach] sinatra.configure
|
193
|
+
# Run once, at startup, when the environment is set to `${1--1}`
|
194
|
+
# @scope class
|
195
|
+
# @attribute
|
196
|
+
# @overload configure ${1--1}
|
117
197
|
configure :development do
|
118
198
|
use Mango::Rack::Debugger
|
119
199
|
end
|
120
200
|
|
121
|
-
#
|
122
|
-
|
123
|
-
|
201
|
+
# Supported JavaScript template engines
|
202
|
+
JAVASCRIPT_TEMPLATE_ENGINES = {
|
203
|
+
Tilt::CoffeeScriptTemplate => :coffee
|
204
|
+
}
|
205
|
+
|
206
|
+
# Supported stylesheet template engines
|
207
|
+
STYLESHEET_TEMPLATE_ENGINES = {
|
208
|
+
Tilt::ScssTemplate => :scss,
|
209
|
+
Tilt::SassTemplate => :sass
|
210
|
+
}
|
211
|
+
|
212
|
+
# Supported view template engines
|
213
|
+
VIEW_TEMPLATE_ENGINES = {
|
214
|
+
Tilt::HamlTemplate => :haml,
|
215
|
+
Tilt::ERBTemplate => :erb,
|
216
|
+
Tilt::LiquidTemplate => :liquid
|
217
|
+
}
|
218
|
+
|
219
|
+
###############################################################################################
|
220
|
+
|
221
|
+
private
|
124
222
|
|
125
|
-
# Renders
|
126
|
-
# response.
|
223
|
+
# Renders a 404 page with a 404 HTTP response code.
|
127
224
|
#
|
128
|
-
#
|
129
|
-
#
|
225
|
+
# First, the application attempts to render a public 404 file stored in `settings.public`. If
|
226
|
+
# a public 404 file is found, the application will:
|
227
|
+
#
|
228
|
+
# * Send the public 404 file with a 404 HTTP response code
|
229
|
+
# * Halt execution
|
230
|
+
#
|
231
|
+
# For example:
|
232
|
+
#
|
233
|
+
# `-- themes
|
234
|
+
# `-- default
|
235
|
+
# `-- public
|
236
|
+
# `-- 404.html
|
237
|
+
#
|
238
|
+
# GET /page_not_found => 404 themes/default/public/404.html
|
239
|
+
#
|
240
|
+
# If no match is found, the application attempts to render a 404 template stored in
|
241
|
+
# `settings.views`. If a 404 template is found, the application *will not* render it within a
|
242
|
+
# layout template, even if an appropriately named layout template exists within
|
243
|
+
# `settings.views`. If a 404 template is found, the application will:
|
244
|
+
#
|
245
|
+
# * Render the 404 template, without a layout template, as HTML
|
246
|
+
# * Send the rendered 404 template with a 404 HTTP response code
|
247
|
+
# * Halt execution
|
130
248
|
#
|
131
249
|
# For example:
|
132
250
|
#
|
@@ -139,16 +257,53 @@ module Mango
|
|
139
257
|
#
|
140
258
|
# GET /page_not_found => 404 themes/default/views/404.haml
|
141
259
|
#
|
260
|
+
# Finally, if no matches are found, the application sends a basic "Page Not Found" page with a
|
261
|
+
# 404 HTTP response code.
|
262
|
+
#
|
263
|
+
# @method not_found
|
264
|
+
# @visibility public
|
265
|
+
#
|
142
266
|
not_found do
|
143
|
-
|
267
|
+
file_name = "404"
|
268
|
+
render_404_public_file! file_name
|
269
|
+
render_404_template! file_name
|
270
|
+
"<!DOCTYPE html><title>404 Page Not Found</title><h1>404 Page Not Found</h1>"
|
144
271
|
end
|
145
272
|
|
146
|
-
#
|
273
|
+
# Given a file name, attempts to send an public 404 file, if it exists, and halt
|
147
274
|
#
|
148
|
-
#
|
149
|
-
# `settings.public`. If a public CSS file is found, the handler will:
|
275
|
+
# @param [String] file_name
|
150
276
|
#
|
151
|
-
|
277
|
+
def render_404_public_file!(file_name)
|
278
|
+
four_oh_four_path = File.expand_path("#{file_name}.html", settings.public)
|
279
|
+
return unless File.file?(four_oh_four_path)
|
280
|
+
send_file four_oh_four_path
|
281
|
+
end
|
282
|
+
|
283
|
+
# Given a template name, and with a prioritized list of template engines, attempts to render a
|
284
|
+
# 404 template, if one exists, and halt.
|
285
|
+
#
|
286
|
+
# @param [String] template_name
|
287
|
+
# @see VIEW_TEMPLATE_ENGINES
|
288
|
+
#
|
289
|
+
def render_404_template!(template_name)
|
290
|
+
VIEW_TEMPLATE_ENGINES.each do |engine, extension|
|
291
|
+
@preferred_extension = extension.to_s
|
292
|
+
find_template(settings.views, template_name, engine) do |file|
|
293
|
+
next unless File.file?(file)
|
294
|
+
halt send(extension, template_name.to_sym, :layout => false)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
###############################################################################################
|
300
|
+
|
301
|
+
# Attempts to render JavaScript templates found within `settings.javascripts`
|
302
|
+
#
|
303
|
+
# First, the application attempts to match the URI path with a public JavaScript file stored in
|
304
|
+
# `settings.public`. If a public JavaScript file is found, the application will:
|
305
|
+
#
|
306
|
+
# * Send the public JavaScript file with a 200 HTTP response code
|
152
307
|
# * Halt execution
|
153
308
|
#
|
154
309
|
# For example:
|
@@ -156,68 +311,135 @@ module Mango
|
|
156
311
|
# `-- themes
|
157
312
|
# `-- default
|
158
313
|
# `-- public
|
159
|
-
# `--
|
160
|
-
# `--
|
314
|
+
# `-- javascripts
|
315
|
+
# `-- jquery.js
|
161
316
|
#
|
162
|
-
# GET /
|
317
|
+
# GET /javascripts/jquery.js => 200 themes/default/public/javascripts/jquery.js
|
163
318
|
#
|
164
|
-
# If no match is found, the route handler attempts to match the URI path with a
|
165
|
-
# template stored in `settings.
|
319
|
+
# If no match is found, the route handler attempts to match the URI path with a JavaScript
|
320
|
+
# template stored in `settings.javascripts`. If a JavaScript template is found, the
|
321
|
+
# application will:
|
166
322
|
#
|
167
|
-
# *
|
168
|
-
# * Send the
|
323
|
+
# * Render the template as Javascript
|
324
|
+
# * Send the rendered template with a 200 HTTP response code
|
169
325
|
# * Halt execution
|
170
326
|
#
|
171
327
|
# For example:
|
172
328
|
#
|
173
329
|
# `-- themes
|
174
330
|
# `-- default
|
175
|
-
# `--
|
176
|
-
# `--
|
331
|
+
# `-- javascripts
|
332
|
+
# `-- bundle.coffee
|
177
333
|
#
|
178
|
-
# GET /
|
334
|
+
# GET /javascripts/bundle.js => 200 themes/default/javascripts/bundle.coffee
|
179
335
|
#
|
180
|
-
# **It's intended that requests to public
|
181
|
-
# the `/
|
336
|
+
# **It's intended that requests to public JavaScript files and requests to JavaScript templates
|
337
|
+
# share the `/javascripts/` prefix.**
|
182
338
|
#
|
183
339
|
# Finally, if no matches are found, the route handler passes execution to the `NOT_FOUND` error
|
184
340
|
# handler.
|
185
341
|
#
|
186
|
-
|
187
|
-
|
342
|
+
# @macro [attach] sinatra.get
|
343
|
+
# @overload get "$1"
|
344
|
+
# @visibility public
|
345
|
+
# @method get_js
|
346
|
+
#
|
347
|
+
get "/javascripts/*.js" do |uri_path|
|
348
|
+
render_javascript_template! uri_path
|
188
349
|
not_found
|
189
350
|
end
|
190
351
|
|
191
|
-
|
192
|
-
|
193
|
-
private
|
194
|
-
|
195
|
-
# Given a URI path, attempts to render a style sheet, if it exists, and halt
|
352
|
+
# Given a URI path, attempts to render a JavaScript template, if it exists, and halt
|
196
353
|
#
|
197
354
|
# @param [String] uri_path
|
355
|
+
# @see JAVASCRIPT_TEMPLATE_ENGINES
|
198
356
|
#
|
199
|
-
def
|
200
|
-
|
201
|
-
|
357
|
+
def render_javascript_template!(uri_path)
|
358
|
+
javascript_match = File.join(settings.javascripts, "*")
|
359
|
+
javascript_path = File.expand_path(uri_path, settings.javascripts)
|
202
360
|
|
203
|
-
return unless File.fnmatch(
|
204
|
-
return unless File.file?(style_sheet_path)
|
361
|
+
return unless File.fnmatch(javascript_match, javascript_path)
|
205
362
|
|
206
|
-
|
207
|
-
|
363
|
+
JAVASCRIPT_TEMPLATE_ENGINES.each do |engine, extension|
|
364
|
+
@preferred_extension = extension.to_s
|
365
|
+
find_template(settings.javascripts, uri_path, engine) do |file|
|
366
|
+
next unless File.file?(file)
|
367
|
+
halt send(extension, uri_path.to_sym, :views => settings.javascripts)
|
368
|
+
end
|
369
|
+
end
|
208
370
|
end
|
209
371
|
|
210
|
-
|
372
|
+
###############################################################################################
|
373
|
+
|
374
|
+
# Attempts to render stylesheet templates found within `settings.stylesheets`
|
375
|
+
#
|
376
|
+
# First, the application attempts to match the URI path with a public stylesheet file stored in
|
377
|
+
# `settings.public`. If a public stylesheet file is found, the application will:
|
378
|
+
#
|
379
|
+
# * Send the public stylesheet file with a 200 HTTP response code
|
380
|
+
# * Halt execution
|
381
|
+
#
|
382
|
+
# For example:
|
383
|
+
#
|
384
|
+
# `-- themes
|
385
|
+
# `-- default
|
386
|
+
# `-- public
|
387
|
+
# `-- stylesheets
|
388
|
+
# `-- reset.css
|
389
|
+
#
|
390
|
+
# GET /stylesheets/reset.css => 200 themes/default/public/stylesheets/reset.css
|
391
|
+
#
|
392
|
+
# If no match is found, the route handler attempts to match the URI path with a stylesheet
|
393
|
+
# template stored in `settings.stylesheets`. If a stylesheet template is found, the
|
394
|
+
# application will:
|
395
|
+
#
|
396
|
+
# * Render the template as CSS
|
397
|
+
# * Send the rendered template with a 200 HTTP response code
|
398
|
+
# * Halt execution
|
399
|
+
#
|
400
|
+
# For example:
|
401
|
+
#
|
402
|
+
# `-- themes
|
403
|
+
# `-- default
|
404
|
+
# `-- stylesheets
|
405
|
+
# `-- screen.scss
|
406
|
+
#
|
407
|
+
# GET /stylesheets/screen.css => 200 themes/default/stylesheets/screen.scss
|
408
|
+
#
|
409
|
+
# **It's intended that requests to public stylesheet files and requests to stylesheet templates
|
410
|
+
# share the `/stylesheets/` prefix.**
|
411
|
+
#
|
412
|
+
# Finally, if no matches are found, the route handler passes execution to the `NOT_FOUND` error
|
413
|
+
# handler.
|
414
|
+
#
|
415
|
+
# @method get_css
|
416
|
+
#
|
417
|
+
get "/stylesheets/*.css" do |uri_path|
|
418
|
+
render_stylesheet_template! uri_path
|
419
|
+
not_found
|
420
|
+
end
|
421
|
+
|
422
|
+
# Given a URI path, attempts to render a stylesheet template, if it exists, and halt
|
211
423
|
#
|
212
424
|
# @param [String] uri_path
|
213
|
-
# @
|
214
|
-
# @return [String] The path to a potential style sheet
|
425
|
+
# @see STYLESHEET_TEMPLATE_ENGINES
|
215
426
|
#
|
216
|
-
def
|
217
|
-
File.
|
427
|
+
def render_stylesheet_template!(uri_path)
|
428
|
+
stylesheet_match = File.join(settings.stylesheets, "*")
|
429
|
+
stylesheet_path = File.expand_path(uri_path, settings.stylesheets)
|
430
|
+
|
431
|
+
return unless File.fnmatch(stylesheet_match, stylesheet_path)
|
432
|
+
|
433
|
+
STYLESHEET_TEMPLATE_ENGINES.each do |engine, extension|
|
434
|
+
@preferred_extension = extension.to_s
|
435
|
+
find_template(settings.stylesheets, uri_path, engine) do |file|
|
436
|
+
next unless File.file?(file)
|
437
|
+
halt send(extension, uri_path.to_sym, :views => settings.stylesheets)
|
438
|
+
end
|
439
|
+
end
|
218
440
|
end
|
219
441
|
|
220
|
-
|
442
|
+
###############################################################################################
|
221
443
|
|
222
444
|
# Attempts to render content page templates found within `settings.content`
|
223
445
|
#
|
@@ -237,52 +459,55 @@ module Mango
|
|
237
459
|
# GET /hello_word.html => 200 themes/default/public/hello_word.html
|
238
460
|
#
|
239
461
|
# If no match is found, the route handler attempts to match the URI path with a content page
|
240
|
-
# template stored in `settings.content`. If a content page template is found, the
|
462
|
+
# template stored in `settings.content`. If a content page template is found, the application
|
463
|
+
# will:
|
241
464
|
#
|
242
|
-
# * Read the content page
|
465
|
+
# * Read the content page from disk and render the data in memory
|
243
466
|
# * Render the content page's view template file (see `Mango::ContentPages`)
|
244
|
-
# *
|
467
|
+
# * An exception is raised if a registered engine for the view template file cannot be
|
468
|
+
# found or if the view template file cannot be found within `settings.views`.
|
245
469
|
# * Send the rendered page with a 200 HTTP response code and halt execution
|
246
470
|
#
|
247
|
-
# In addition, if a `layout
|
248
|
-
# template
|
471
|
+
# In addition, if a `layout` template file exists within `settings.views` and that layout
|
472
|
+
# template file shares the same file extension as the view template, then the page's view
|
473
|
+
# template is wrapped within this layout template when rendered.
|
249
474
|
#
|
250
|
-
# For example:
|
475
|
+
# For example, given the following mango application:
|
251
476
|
#
|
252
477
|
# |-- content
|
253
|
-
# | `-- index.
|
478
|
+
# | `-- index.markdown
|
254
479
|
# `-- themes
|
255
480
|
# `-- default
|
256
481
|
# `-- views
|
257
482
|
# |-- layout.haml
|
258
483
|
# `-- page.haml
|
259
484
|
#
|
260
|
-
#
|
485
|
+
# where the `index.markdown` content page's view template file is `page.haml`, then:
|
486
|
+
#
|
487
|
+
# GET /index => 200 content/index.markdown +
|
261
488
|
# themes/default/views/page.haml +
|
262
489
|
# themes/default/views/layout.haml
|
263
490
|
#
|
264
491
|
# Finally, if no matches are found, the route handler passes execution to the `NOT_FOUND` error
|
265
492
|
# handler.
|
266
493
|
#
|
494
|
+
# @method get_all
|
495
|
+
#
|
267
496
|
get "/*" do |uri_path|
|
268
497
|
render_index_file! uri_path
|
269
498
|
render_content_page! uri_path
|
270
499
|
not_found
|
271
500
|
end
|
272
501
|
|
273
|
-
###############################################################################################
|
274
|
-
|
275
|
-
private
|
276
|
-
|
277
502
|
# Given a URI path, attempts to send an index.html file, if it exists, and halt
|
278
503
|
#
|
279
504
|
# @param [String] uri_path
|
280
505
|
#
|
281
506
|
def render_index_file!(uri_path)
|
282
|
-
return unless
|
507
|
+
return unless URI.directory?(uri_path)
|
283
508
|
|
284
509
|
index_match = File.join(settings.public, "*")
|
285
|
-
index_file_path =
|
510
|
+
index_file_path = File.expand_path(uri_path + "index.html", settings.public)
|
286
511
|
|
287
512
|
return unless File.fnmatch(index_match, index_file_path)
|
288
513
|
return unless File.file?(index_file_path)
|
@@ -290,65 +515,72 @@ module Mango
|
|
290
515
|
send_file index_file_path
|
291
516
|
end
|
292
517
|
|
293
|
-
#
|
294
|
-
|
295
|
-
# @param [String] uri_path
|
296
|
-
# @return [String] The path to a potential index.html file
|
297
|
-
#
|
298
|
-
def build_index_file_path(uri_path)
|
299
|
-
uri_path += "index.html"
|
300
|
-
File.expand_path(uri_path, settings.public)
|
301
|
-
end
|
518
|
+
# Raised when a content page is not found on disk
|
519
|
+
class ContentPageNotFound < RuntimeError; end
|
302
520
|
|
303
|
-
|
521
|
+
# Raised when a registered engine for the content page's view template cannot be found in
|
522
|
+
# `VIEW_TEMPLATE_ENGINES`
|
523
|
+
class RegisteredEngineNotFound < RuntimeError; end
|
304
524
|
|
305
|
-
|
525
|
+
# Raised when the content page's view template cannot be found on disk
|
526
|
+
class ViewTemplateNotFound < RuntimeError; end
|
306
527
|
|
307
528
|
# Given a URI path, attempts to render a content page, if it exists, and halt
|
308
529
|
#
|
309
530
|
# @param [String] uri_path
|
310
|
-
# @raise [
|
531
|
+
# @raise [RegisteredEngineNotFound] Raised when a registered engine for the content page's
|
532
|
+
# view template cannot be found
|
533
|
+
# @raise [ViewTemplateNotFound] Raised when the content page's view template cannot be found
|
311
534
|
#
|
312
535
|
def render_content_page!(uri_path)
|
536
|
+
uri_path += "index" if URI.directory?(uri_path)
|
537
|
+
|
313
538
|
content_match = File.join(settings.content, "*")
|
314
|
-
content_page_path =
|
539
|
+
content_page_path = File.expand_path(uri_path, settings.content)
|
315
540
|
return unless File.fnmatch(content_match, content_page_path)
|
316
541
|
|
317
542
|
begin
|
318
|
-
|
319
|
-
rescue
|
543
|
+
content_page = find_content_page(uri_path)
|
544
|
+
rescue ContentPageNotFound
|
320
545
|
return
|
321
546
|
end
|
322
547
|
|
548
|
+
view_template_path = File.expand_path(content_page.view, settings.views)
|
549
|
+
|
550
|
+
begin
|
551
|
+
engine = VIEW_TEMPLATE_ENGINES.fetch(Tilt[content_page.view])
|
552
|
+
rescue KeyError
|
553
|
+
message = "Cannot find registered engine for view template file -- #{view_template_path}"
|
554
|
+
raise RegisteredEngineNotFound, message
|
555
|
+
end
|
556
|
+
|
323
557
|
begin
|
324
|
-
halt
|
558
|
+
halt send(engine, content_page.view.to_s.templatize, :locals => { :page => content_page })
|
325
559
|
rescue Errno::ENOENT
|
326
|
-
|
327
|
-
raise
|
560
|
+
message = "Cannot find view template file -- #{view_template_path}"
|
561
|
+
raise ViewTemplateNotFound, message
|
328
562
|
end
|
329
563
|
end
|
330
564
|
|
331
|
-
# Given a URI path,
|
565
|
+
# Given a URI path, creates a new `ContentPage` instance by searching for and reading a content
|
566
|
+
# file from disk. Content files are searched consecutively until a page with a supported
|
567
|
+
# content page template engine is found.
|
332
568
|
#
|
333
569
|
# @param [String] uri_path
|
334
|
-
# @
|
335
|
-
#
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
570
|
+
# @raise [ContentPageNotFound] Raised when a content page cannot be found for the uri path
|
571
|
+
# @return [ContentPage] A new instance is created and returned when found
|
572
|
+
# @see ContentPage::TEMPLATE_ENGINES
|
573
|
+
#
|
574
|
+
def find_content_page(uri_path)
|
575
|
+
ContentPage::TEMPLATE_ENGINES.each do |engine, extension|
|
576
|
+
@preferred_extension = extension.to_s
|
577
|
+
find_template(settings.content, uri_path, engine) do |file|
|
578
|
+
next unless File.file?(file)
|
579
|
+
return ContentPage.new(:data => File.read(file), :engine => engine)
|
580
|
+
end
|
581
|
+
end
|
344
582
|
|
345
|
-
|
346
|
-
#
|
347
|
-
# @param [String] uri_path
|
348
|
-
# @return [Boolean] `true` if the path is empty or has a trailing `/`, otherwise `false`
|
349
|
-
#
|
350
|
-
def directory_path?(uri_path)
|
351
|
-
uri_path.empty? || uri_path[-1] == "/"
|
583
|
+
raise ContentPageNotFound, "Cannot find content page for path -- #{uri_path}"
|
352
584
|
end
|
353
585
|
end
|
354
586
|
end
|