mango 0.5.4 → 0.6.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/.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
|