mango 0.1.1 → 0.5.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.yardopts +6 -0
- data/README.mdown +62 -29
- data/Rakefile +62 -0
- data/VERSION +1 -0
- data/bin/mango +5 -0
- data/doc/HISTORY.mdown +71 -0
- data/doc/ROAD-MAP.mdown +10 -0
- data/lib/mango.rb +7 -0
- data/lib/mango/application.rb +334 -0
- data/lib/mango/content_page.rb +193 -0
- data/lib/mango/dependencies.rb +125 -0
- data/lib/mango/flavored_markdown.rb +82 -0
- data/lib/mango/rack/debugger.rb +22 -0
- data/lib/mango/runner.rb +95 -0
- data/lib/mango/templates/Gemfile +4 -0
- data/lib/mango/templates/README.md +1 -0
- data/lib/mango/templates/config.ru +4 -0
- data/lib/mango/templates/content/index.md +5 -0
- data/lib/mango/templates/themes/default/public/images/particles.gif +0 -0
- data/lib/mango/templates/themes/default/public/javascripts/fireworks.js +546 -0
- data/lib/mango/templates/themes/default/public/javascripts/timer.js +5 -0
- data/lib/mango/templates/themes/default/public/robots.txt +5 -0
- data/lib/mango/templates/themes/default/public/styles/fireworks.css +55 -0
- data/lib/mango/templates/themes/default/public/styles/reset.css +54 -0
- data/lib/mango/templates/themes/default/styles/screen.sass +17 -0
- data/lib/mango/templates/themes/default/views/404.haml +21 -0
- data/lib/mango/templates/themes/default/views/layout.haml +20 -0
- data/lib/mango/templates/themes/default/views/page.haml +3 -0
- data/lib/mango/version.rb +6 -0
- data/mango.gemspec +35 -0
- data/spec/app_root/content/about/index.haml +1 -0
- data/spec/app_root/content/about/us.haml +1 -0
- data/spec/app_root/content/engines/haml.haml +7 -0
- data/spec/app_root/content/engines/markdown.markdown +7 -0
- data/spec/app_root/content/engines/md.md +7 -0
- data/spec/app_root/content/engines/mdown.mdown +7 -0
- data/spec/app_root/content/index.haml +1 -0
- data/spec/app_root/content/override.haml +1 -0
- data/spec/app_root/content/page_with_missing_view.haml +4 -0
- data/spec/app_root/content/turner+hooch.haml +1 -0
- data/spec/app_root/security_hole.haml +1 -0
- data/spec/app_root/themes/default/public/default.css +3 -0
- data/spec/app_root/themes/default/public/images/index.html +10 -0
- data/spec/app_root/themes/default/public/images/ripe-mango.jpg +0 -0
- data/spec/app_root/themes/default/public/override +10 -0
- data/spec/app_root/themes/default/public/robots.txt +2 -0
- data/spec/app_root/themes/default/public/styles/override.css +3 -0
- data/spec/app_root/themes/default/public/styles/reset.css +27 -0
- data/spec/app_root/themes/default/public/styles/subfolder/another.css +3 -0
- data/spec/app_root/themes/default/security_hole.sass +1 -0
- data/spec/app_root/themes/default/security_hole.txt +1 -0
- data/spec/app_root/themes/default/styles/override.sass +2 -0
- data/spec/app_root/themes/default/styles/screen.sass +13 -0
- data/spec/app_root/themes/default/styles/subfolder/screen.sass +12 -0
- data/spec/app_root/themes/default/views/404.haml +7 -0
- data/spec/app_root/themes/default/views/layout.haml +7 -0
- data/spec/app_root/themes/default/views/page.haml +4 -0
- data/spec/mango/application/routing_content_pages_spec.rb +357 -0
- data/spec/mango/application/routing_public_files_spec.rb +181 -0
- data/spec/mango/application/routing_style_sheets_spec.rb +286 -0
- data/spec/mango/application_spec.rb +34 -0
- data/spec/mango/content_page/finding_spec.rb +213 -0
- data/spec/mango/content_page/initializing_spec.rb +298 -0
- data/spec/mango/content_page_spec.rb +44 -0
- data/spec/mango/dependencies_spec.rb +189 -0
- data/spec/mango/flavored_markdown_spec.rb +52 -0
- data/spec/mango/rack/debugger_spec.rb +114 -0
- data/spec/mango/version_spec.rb +18 -0
- data/spec/quality_spec.rb +32 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/matchers/malformed_whitespace_matchers.rb +60 -0
- metadata +304 -17
data/.gitignore
ADDED
data/.yardopts
ADDED
data/README.mdown
CHANGED
@@ -2,65 +2,84 @@
|
|
2
2
|
|
3
3
|
Image courtesy of [B.C. Tree Fruits LTD.](http://www.bctree.com/products/sourced/mango.php)
|
4
4
|
|
5
|
-
Mango release 0.
|
6
|
-
|
5
|
+
Mango release 0.5.0 (September 12, 2010)
|
6
|
+
========================================
|
7
7
|
|
8
8
|
Copyright (c) 2010 Ryan Sobol. Licensed under the MIT license. Please see the {file:LICENSE} for more information.
|
9
9
|
|
10
|
-
**Source Code**: [http://github.com/ryansobol/mango](http://github.com/ryansobol/mango)
|
11
|
-
**
|
12
|
-
**
|
10
|
+
* **Source Code**: [http://github.com/ryansobol/mango](http://github.com/ryansobol/mango)
|
11
|
+
* **Documentation**: [http://rubydoc.info/github/ryansobol/mango](http://rubydoc.info/github/ryansobol/mango)
|
12
|
+
* **Bug Tracker**: [http://github.com/ryansobol/mango/issues](http://github.com/ryansobol/mango/issues)
|
13
|
+
* **Wiki**: [http://wiki.github.com/ryansobol/mango](http://wiki.github.com/ryansobol/mango)
|
14
|
+
|
15
|
+
**Mango respects [Semantic Versioning](http://semver.org/)!**
|
13
16
|
|
14
17
|
WHAT'S NEW?
|
15
18
|
-----------
|
16
19
|
|
17
|
-
|
20
|
+
### New Features:
|
21
|
+
|
22
|
+
* Added the beginnings of a default theme titled "Smashing Mangos".
|
23
|
+
* Added `Mango::Rack::Debugger` to the middleware stack (Only loads in the `:development` rack environment).
|
24
|
+
* Added a `Mango::ContentPage` model to convert user-generated content into HTML. Supports either [Haml](http://haml-lang.com/) or [Markdown](http://daringfireball.net/projects/markdown/syntax) formatted content.
|
25
|
+
* Refactored `Mango::Application` to utilize `Mango::ContentPage`. Now views have access to a `@content_page` instance variable.
|
26
|
+
* Added `Mango::FlavoredMarkdown`, a subset of [GithubFlavoredMarkdown](http://github.github.com/github-flavored-markdown/), into the Markdown-to-HTML conversion.
|
27
|
+
|
28
|
+
### Dependencies:
|
29
|
+
|
30
|
+
* Updated [Haml](http://haml-lang.com/) to 3.0.18
|
31
|
+
* Updated [YARD::Sinatra](http://github.com/rkh/yard-sinatra) to 0.5.0
|
32
|
+
* Added [BlueCloth](http://deveiate.org/projects/BlueCloth) 2.0.7 as a required dependency
|
18
33
|
|
19
34
|
Please see {file:doc/HISTORY.mdown} for the historical overview of the project.
|
20
35
|
|
21
36
|
SYNOPSIS
|
22
37
|
--------
|
23
38
|
|
24
|
-
**Mango is a dynamic
|
25
|
-
|
26
|
-
Mango let's you use publish to the web using the tools you're already familiar with -- the file system and your trusty text editor. With Mango, there is:
|
27
|
-
|
28
|
-
* No clunky administrator interface for managing content
|
29
|
-
* No unchangeable database requirements -- no database period!
|
30
|
-
* No know exploits ;)
|
39
|
+
**Mango is a dynamic, database-free, and open source website framework that is designed to make life easier for small teams of designers, developers, and content writers.**
|
31
40
|
|
32
41
|
FEATURES
|
33
42
|
--------
|
34
43
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
44
|
+
1. Easy to install: Mango installs as a RubyGem and can generate a basic website structure in seconds.
|
45
|
+
|
46
|
+
2. Easy to publish: Supports many types of deployments like direct SFTP uploading and source control systems like Git, Mercurial, SVN, CSV, etc.
|
47
|
+
|
48
|
+
3. Easy to write: Mango let's you publish to the web using the tools you're already familiar with -- the file system and your trusty text editor. Mango supports a variety of formats include Markdown, HAML, HTML, SASS, CSS, and JavaScript. These files are easier to create and revise then working with database records. Say goodbye to clunky administrator interfaces for managing content!
|
49
|
+
|
50
|
+
4. Easy to deploy: There's no database to install, configure, and manage.
|
51
|
+
|
52
|
+
5. Easy to understand: Mango is perfect for smalls teams of varying levels of coding expertise. Why not take the simple route where everyone is on the same page? Instead of struggling with complex platforms, which most CMS are, Mango is perfect for people who has no coding experience.
|
53
|
+
|
54
|
+
6. Easy on the wallet: It's free!
|
55
|
+
|
56
|
+
7. Easy to... SPEED: A major advantage of a database-less website framework is speed. Database queries slow down servers. On a high traffic website, this has a dramatic effect on the speed of the site. With minimal server side scripting and zero database queries, Mango is lightening fast.
|
39
57
|
|
40
58
|
REQUIREMENTS
|
41
59
|
------------
|
42
60
|
|
43
61
|
**Required dependencies**
|
44
62
|
|
45
|
-
* Ruby 1.9.1
|
46
|
-
* Rack 1.2.1
|
47
|
-
* Sinatra 1.0
|
48
|
-
* Haml 3.0.
|
63
|
+
* [Ruby](http://www.ruby-lang.org/) 1.9.1
|
64
|
+
* [Rack](http://rack.rubyforge.org/) 1.2.1
|
65
|
+
* [Sinatra](http://www.sinatrarb.com/) 1.0
|
66
|
+
* [Haml](http://haml-lang.com/) 3.0.18
|
67
|
+
* [Sass](http://sass-lang.com/) 3.0.18 (bundled with Haml)
|
68
|
+
* [BlueCloth](http://deveiate.org/projects/BlueCloth) 2.0.7
|
49
69
|
|
50
70
|
**Optional development dependencies**
|
51
71
|
|
52
|
-
* Rake 0.8.7 (bundled with Ruby
|
53
|
-
* Rack::Test 0.5.4
|
54
|
-
* RSpec 1.3.0
|
55
|
-
* YARD 0.5.
|
56
|
-
*
|
72
|
+
* [Rake](http://rake.rubyforge.org/) 0.8.7 (bundled with Ruby)
|
73
|
+
* [Rack::Test](http://github.com/brynary/rack-test) 0.5.4
|
74
|
+
* [RSpec](http://rspec.info/) 1.3.0
|
75
|
+
* [YARD](http://yardoc.org/) 0.5.8
|
76
|
+
* [YARD::Sinatra](http://github.com/rkh/yard-sinatra) 0.5.0
|
77
|
+
* [BlueCloth](http://deveiate.org/projects/BlueCloth) 2.0.7
|
57
78
|
|
58
79
|
INSTALLING
|
59
80
|
----------
|
60
81
|
|
61
|
-
$
|
62
|
-
$ cd mango
|
63
|
-
$ bundle install
|
82
|
+
$ gem install mango
|
64
83
|
|
65
84
|
USAGE
|
66
85
|
-----
|
@@ -75,6 +94,11 @@ USAGE
|
|
75
94
|
`-- themes
|
76
95
|
`-- default
|
77
96
|
|-- public
|
97
|
+
| |-- images
|
98
|
+
| | `-- ripe-mango.jpg
|
99
|
+
| `-- robots.txt
|
100
|
+
|-- styles
|
101
|
+
| `-- screen.sass
|
78
102
|
`-- views
|
79
103
|
|-- 404.haml
|
80
104
|
|-- layout.haml
|
@@ -84,6 +108,15 @@ USAGE
|
|
84
108
|
|
85
109
|
$ rackup
|
86
110
|
|
111
|
+
UNDER THE HOOD
|
112
|
+
--------------
|
113
|
+
|
114
|
+
* Mango tries to route HTTP requests to static files first
|
115
|
+
* Then it tries to route HTTP requests to Markdown or Haml content pages or Sass style templates
|
116
|
+
* Finally, it routes unknown HTTP requests to a customizable 404 page
|
117
|
+
* Wraps content pages within a customizable Haml template and layout
|
118
|
+
* Supports any Rack-based application server (e.g. Phusion Passenger, thin, mongrel, webrick, etc.)
|
119
|
+
|
87
120
|
MOTIVATION
|
88
121
|
----------
|
89
122
|
|
data/Rakefile
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require_relative "lib/mango"
|
3
|
+
Mango::Dependencies.warn_at_exit
|
4
|
+
|
5
|
+
###################################################################################################
|
6
|
+
|
7
|
+
begin
|
8
|
+
require "spec/rake/spectask"
|
9
|
+
require "rack/test" # for Rack support
|
10
|
+
Spec::Rake::SpecTask.new(:spec)
|
11
|
+
task :default => :spec
|
12
|
+
rescue LoadError => e
|
13
|
+
Mango::Dependencies.create_warning_for(e)
|
14
|
+
end
|
15
|
+
|
16
|
+
###################################################################################################
|
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
|
+
namespace :gem do
|
32
|
+
desc "Builds a gem from the current project's Gem::Specification"
|
33
|
+
task :build do
|
34
|
+
system "gem build mango.gemspec"
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Removes the gem file for the current project"
|
38
|
+
task :clean do
|
39
|
+
jeweler { |gem_file| rm gem_file }
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "Pushes the current gem to RubyGems.org"
|
43
|
+
task :push do
|
44
|
+
jeweler { |gem_file| system "gem push #{gem_file}"}
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Builds, pushes, and cleans a gem for the current project"
|
48
|
+
task :release do
|
49
|
+
Rake::Task["gem:build"].invoke
|
50
|
+
Rake::Task["gem:push"].invoke
|
51
|
+
Rake::Task["gem:clean"].invoke
|
52
|
+
end
|
53
|
+
|
54
|
+
def jeweler(&block)
|
55
|
+
file = "mango-#{Mango::VERSION}.gem"
|
56
|
+
if File.exists?(file)
|
57
|
+
yield file
|
58
|
+
else
|
59
|
+
puts "No gem file found - #{file}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.0.beta1
|
data/bin/mango
ADDED
data/doc/HISTORY.mdown
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
Mango release 0.5.0 (September 12, 2010)
|
2
|
+
========================================
|
3
|
+
|
4
|
+
|
5
|
+
Mango release 0.4.0 (August 30, 2010)
|
6
|
+
=====================================
|
7
|
+
|
8
|
+
### New Features:
|
9
|
+
|
10
|
+
* Added the beginnings of a default theme titled "Smashing Mangos".
|
11
|
+
* Added `Mango::Rack::Debugger` to the middleware stack (Only loads in the `:development` rack environment).
|
12
|
+
* Added a `Mango::ContentPage` model to convert user-generated content into HTML. Supports either [Haml](http://haml-lang.com/) or [Markdown](http://daringfireball.net/projects/markdown/syntax) formatted content.
|
13
|
+
* Refactored `Mango::Application` to utilize `Mango::ContentPage`. Now views have access to a `@content_page` instance variable.
|
14
|
+
* Added `Mango::FlavoredMarkdown`, a subset of [GithubFlavoredMarkdown](http://github.github.com/github-flavored-markdown/), into the Markdown-to-HTML conversion.
|
15
|
+
|
16
|
+
### Dependencies:
|
17
|
+
|
18
|
+
* Updated [Haml](http://haml-lang.com/) to 3.0.18
|
19
|
+
* Updated [YARD::Sinatra](http://github.com/rkh/yard-sinatra) to 0.5.0
|
20
|
+
* Added [BlueCloth](http://deveiate.org/projects/BlueCloth) 2.0.7 as a required dependency
|
21
|
+
|
22
|
+
Mango release 0.3.0 (June 25, 2010)
|
23
|
+
===================================
|
24
|
+
|
25
|
+
### New Features:
|
26
|
+
|
27
|
+
* Added a route handler that renders [Sass](http://sass-lang.com/) templates to CSS!
|
28
|
+
* Refactored tests for better spec coverage of route handling
|
29
|
+
* Massive rewrite of internal documentation thanks to the [YARD::Sinatra (modified)](http://github.com/ryansobol/yard-sinatra)
|
30
|
+
* Uploaded developer documentation to [http://yardoc.org/docs/ryansobol-mango](http://yardoc.org/docs/ryansobol-mango)
|
31
|
+
|
32
|
+
### Dependencies:
|
33
|
+
|
34
|
+
* Updated [Haml](http://haml-lang.com/) to 3.0.13
|
35
|
+
* Added [YARD::Sinatra](http://github.com/rkh/yard-sinatra) 0.4.0.1 [(modified)](http://github.com/ryansobol/yard-sinatra)
|
36
|
+
|
37
|
+
### Bug fixes:
|
38
|
+
|
39
|
+
* Fixed Regex when parsing LoadError messages on missing development dependencies
|
40
|
+
* Fixed rspec gem name detection when requiring spec/rake/spectask in the Rakefile
|
41
|
+
|
42
|
+
Mango release 0.2.1 (June 23, 2010)
|
43
|
+
===================================
|
44
|
+
|
45
|
+
* Refactored the application to reduce its code size and increase its maintainability
|
46
|
+
* Improved the application's documentation and tests with additional HTTP routing examples
|
47
|
+
|
48
|
+
Mango release 0.2.0 (June 19, 2010)
|
49
|
+
===================================
|
50
|
+
|
51
|
+
* Mango tries to route HTTP requests to static files first
|
52
|
+
* Then it tries to route HTTP requests to Haml content pages
|
53
|
+
* Finally, it routes unknown HTTP requests to a customizable 404 page
|
54
|
+
|
55
|
+
Mango release 0.1.1 (June 15, 2010)
|
56
|
+
===================================
|
57
|
+
|
58
|
+
* Reserved the 'mango' namespace on RubyGems.org!
|
59
|
+
|
60
|
+
Mango release 0.1.0 (June 15, 2010)
|
61
|
+
===================================
|
62
|
+
|
63
|
+
* Mango tries to route HTTP requests to Haml content pages first
|
64
|
+
* Then it routes unknown HTTP requests to a customizable 404 page
|
65
|
+
* Wraps content pages within a customizable Haml template and layout
|
66
|
+
* Supports any Rack-based application server (e.g. Phusion Passenger, thin, mongrel, webrick, etc.)
|
67
|
+
|
68
|
+
Mango unrelease 0.0.1 (June 12, 2010)
|
69
|
+
=====================================
|
70
|
+
|
71
|
+
* First commit of the project
|
data/doc/ROAD-MAP.mdown
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
Road-map of Potential Improvements
|
2
|
+
==================================
|
3
|
+
|
4
|
+
In no particular order of importance:
|
5
|
+
|
6
|
+
Mango::Dependencies
|
7
|
+
-------------------
|
8
|
+
|
9
|
+
* Compare, contrast, extend, and/or integrate with Bundler
|
10
|
+
* Promote the installation and use of RVM
|
data/lib/mango.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require_relative "mango/dependencies" # ruby version guard
|
3
|
+
require_relative "mango/version"
|
4
|
+
require_relative "mango/rack/debugger"
|
5
|
+
require_relative "mango/application"
|
6
|
+
require_relative "mango/flavored_markdown"
|
7
|
+
require_relative "mango/content_page"
|
@@ -0,0 +1,334 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require "sinatra/base"
|
3
|
+
require "haml"
|
4
|
+
require "sass"
|
5
|
+
|
6
|
+
module Mango
|
7
|
+
# It's probably no surprise that `Mango::Application` is a modular **application controller**
|
8
|
+
# class, inheriting all of the magic and wonder of `Sinatra::Base`. The primary responsibility
|
9
|
+
# of the class is to receive an HTTP request and send an HTML response by instructing the
|
10
|
+
# necessary models and/or views to perform actions based on that request.
|
11
|
+
#
|
12
|
+
# For **every HTTP request**, the application will first attempt to match the request URI path to
|
13
|
+
# a public file found within `settings.public` and send that file with a 200 response code.
|
14
|
+
#
|
15
|
+
# In addition to serving static assets, the application has two dynamic route handlers:
|
16
|
+
#
|
17
|
+
# * Content page templates with `GET *`
|
18
|
+
# * Style sheet templates with `GET /styles/*.css`
|
19
|
+
#
|
20
|
+
# and one error handler:
|
21
|
+
#
|
22
|
+
# * 404 Page Not Found with `NOT_FOUND`
|
23
|
+
#
|
24
|
+
# # Serving public files found within `settings.public`
|
25
|
+
#
|
26
|
+
# ### Example requests routed to public files (with potential security holes)
|
27
|
+
#
|
28
|
+
# |-- content
|
29
|
+
# | `-- override.haml
|
30
|
+
# `-- themes
|
31
|
+
# `-- default
|
32
|
+
# |-- public
|
33
|
+
# | |-- images
|
34
|
+
# | | |-- index.html
|
35
|
+
# | | `-- ripe-mango.jpg
|
36
|
+
# | |-- override
|
37
|
+
# | `-- robots.txt
|
38
|
+
# `-- security_hole.txt
|
39
|
+
#
|
40
|
+
# GET /robots.txt => 200 themes/default/public/robots.txt
|
41
|
+
# GET /images/index.html => 200 themes/default/public/images/index.html
|
42
|
+
# GET /images/ripe-mango.jpg => 200 themes/default/public/images/ripe-mango.jpg
|
43
|
+
# GET /override => 200 themes/default/public/override
|
44
|
+
# GET /images/ => 200 themes/default/public/images/index.html
|
45
|
+
#
|
46
|
+
# GET /../security_hole.txt => pass to NOT_FOUND error handler
|
47
|
+
#
|
48
|
+
# # Content page templates with `GET *`
|
49
|
+
#
|
50
|
+
# ### Example `GET *` requests routed to content pages (with potential security holes)
|
51
|
+
#
|
52
|
+
# |-- content
|
53
|
+
# | |-- about
|
54
|
+
# | | |-- index.haml
|
55
|
+
# | | `-- us.haml
|
56
|
+
# | |-- index.haml
|
57
|
+
# | |-- override.haml
|
58
|
+
# | `-- turner+hooch.haml
|
59
|
+
# `-- security_hole.haml
|
60
|
+
#
|
61
|
+
# GET / => 200 content/index.haml
|
62
|
+
# GET /index => 200 content/index.haml
|
63
|
+
# GET /index?foo=bar => 200 content/index.haml
|
64
|
+
# GET /about/ => 200 content/about/index.haml
|
65
|
+
# GET /about/index => 200 content/about/index.haml
|
66
|
+
# GET /about/us => 200 content/about/us.haml
|
67
|
+
# GET /turner%2Bhooch => 200 content/turner+hooch.haml
|
68
|
+
#
|
69
|
+
# GET /page_not_found => pass to NOT_FOUND error handler
|
70
|
+
# GET /../security_hole => pass to NOT_FOUND error handler
|
71
|
+
#
|
72
|
+
# # Style sheet templates with `GET /styles/*.css`
|
73
|
+
#
|
74
|
+
# ### Example `GET /styles/*.css` requests routed to style sheets (with potential security holes)
|
75
|
+
#
|
76
|
+
# `-- themes
|
77
|
+
# `-- default
|
78
|
+
# |-- public
|
79
|
+
# | |-- default.css
|
80
|
+
# | `-- styles
|
81
|
+
# | |-- override.css
|
82
|
+
# | |-- reset.css
|
83
|
+
# | `-- subfolder
|
84
|
+
# | `-- another.css
|
85
|
+
# |-- security_hole.sass
|
86
|
+
# `-- styles
|
87
|
+
# |-- override.sass
|
88
|
+
# |-- screen.sass
|
89
|
+
# `-- subfolder
|
90
|
+
# `-- screen.sass
|
91
|
+
#
|
92
|
+
# GET /styles/screen.css => 200 themes/default/styles/screen.sass
|
93
|
+
# GET /styles/subfolder/screen.css => 200 themes/default/styles/subfolder/screen.sass
|
94
|
+
#
|
95
|
+
# GET /styles/reset.css => 200 themes/default/public/styles/reset.css
|
96
|
+
# GET /styles/override.css => 200 themes/default/public/styles/override.css
|
97
|
+
# GET /default.css => 200 themes/default/public/default.css
|
98
|
+
# GET /styles/subfolder/another.css => 200 themes/default/public/styles/subfolder/another.css
|
99
|
+
#
|
100
|
+
# GET /styles/style_not_found.css => pass to NOT_FOUND error handler
|
101
|
+
# GET /screen.css => pass to NOT_FOUND error handler
|
102
|
+
# GET /styles/../security_hole.css => pass to NOT_FOUND error handler
|
103
|
+
#
|
104
|
+
# # 404 Page Not Found with `NOT_FOUND`
|
105
|
+
#
|
106
|
+
# When a requested URI path cannot be matched with a public file or template file, the error
|
107
|
+
# handler renders the 404 template and sends it with a 404 response.
|
108
|
+
#
|
109
|
+
class Application < Sinatra::Base
|
110
|
+
set :root, Dir.getwd
|
111
|
+
set :theme, "default"
|
112
|
+
set :views, lambda { File.join(root, "themes", theme, "views") }
|
113
|
+
set :public, lambda { File.join(root, "themes", theme, "public") }
|
114
|
+
set :styles, lambda { File.join(root, "themes", theme, "styles") }
|
115
|
+
set :content, lambda { File.join(root, "content") }
|
116
|
+
|
117
|
+
# Renders the `404.haml` template found within `settings.views` and sends it with 404 HTTP
|
118
|
+
# response.
|
119
|
+
#
|
120
|
+
# The `404.haml` template is **not** wrapped within the `layout.haml` template when rendered,
|
121
|
+
# even if one exists within `settings.views`.
|
122
|
+
#
|
123
|
+
# For example:
|
124
|
+
#
|
125
|
+
# |-- content
|
126
|
+
# | `-- index.haml
|
127
|
+
# `-- themes
|
128
|
+
# `-- default
|
129
|
+
# `-- views
|
130
|
+
# `-- 404.haml
|
131
|
+
#
|
132
|
+
# GET /page_not_found => 404 themes/default/views/404.haml
|
133
|
+
#
|
134
|
+
not_found do
|
135
|
+
haml :"404", :layout => false
|
136
|
+
end
|
137
|
+
|
138
|
+
# Attempts to render style sheet templates found within `settings.styles`
|
139
|
+
#
|
140
|
+
# First, the application attempts to match the URI path with a public CSS file stored in
|
141
|
+
# `settings.public`. If a public CSS file is found, the handler will:
|
142
|
+
#
|
143
|
+
# * Send the public CSS file with a 200 HTTP response code
|
144
|
+
# * Halt execution
|
145
|
+
#
|
146
|
+
# For example:
|
147
|
+
#
|
148
|
+
# `-- themes
|
149
|
+
# `-- default
|
150
|
+
# `-- public
|
151
|
+
# `-- styles
|
152
|
+
# `-- reset.css
|
153
|
+
#
|
154
|
+
# GET /styles/reset.css => 200 themes/default/public/styles/reset.css
|
155
|
+
#
|
156
|
+
# If no match is found, the route handler attempts to match the URI path with a style sheet
|
157
|
+
# template stored in `settings.styles`. If a style sheet template is found, the handler will:
|
158
|
+
#
|
159
|
+
# * Convert the style sheet template from Sass to CSS
|
160
|
+
# * Send the converted style with a 200 HTTP response code
|
161
|
+
# * Halt execution
|
162
|
+
#
|
163
|
+
# For example:
|
164
|
+
#
|
165
|
+
# `-- themes
|
166
|
+
# `-- default
|
167
|
+
# `-- styles
|
168
|
+
# `-- screen.sass
|
169
|
+
#
|
170
|
+
# GET /styles/screen.css => 200 themes/default/styles/screen.sass
|
171
|
+
#
|
172
|
+
# **It's intended that requests to public CSS files and requests to style sheet templates share
|
173
|
+
# the `/styles/` prefix.**
|
174
|
+
#
|
175
|
+
# Finally, if no matches are found, the route handler passes execution to the `NOT_FOUND` error
|
176
|
+
# handler.
|
177
|
+
#
|
178
|
+
get "/styles/*.css" do |uri_path|
|
179
|
+
render_style_sheet! uri_path
|
180
|
+
not_found
|
181
|
+
end
|
182
|
+
|
183
|
+
###############################################################################################
|
184
|
+
|
185
|
+
private
|
186
|
+
|
187
|
+
# Given a URI path, attempts to render a style sheet, if it exists, and halt
|
188
|
+
#
|
189
|
+
# @param [String] uri_path
|
190
|
+
#
|
191
|
+
def render_style_sheet!(uri_path)
|
192
|
+
styles_match = File.join(settings.styles, "*")
|
193
|
+
style_sheet_path = build_style_sheet_path(uri_path)
|
194
|
+
|
195
|
+
return unless File.fnmatch(styles_match, style_sheet_path)
|
196
|
+
return unless File.file?(style_sheet_path)
|
197
|
+
|
198
|
+
content_type "text/css"
|
199
|
+
halt sass(uri_path.to_sym, :views => settings.styles)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Given a URI path, build a path to a potential style sheet
|
203
|
+
#
|
204
|
+
# @param [String] uri_path
|
205
|
+
# @param [String] format (defaults to `sass`)
|
206
|
+
# @return [String] The path to a potential style sheet
|
207
|
+
#
|
208
|
+
def build_style_sheet_path(uri_path, format = "sass")
|
209
|
+
File.expand_path("#{uri_path}.#{format}", settings.styles)
|
210
|
+
end
|
211
|
+
|
212
|
+
public
|
213
|
+
|
214
|
+
# Attempts to render content page templates found within `settings.content`
|
215
|
+
#
|
216
|
+
# First, the application attempts to match the URI path with a public file stored in
|
217
|
+
# `settings.public`. If a public file is found, the handler will:
|
218
|
+
#
|
219
|
+
# * Send the public file with a 200 HTTP response code
|
220
|
+
# * Halt execution
|
221
|
+
#
|
222
|
+
# For example:
|
223
|
+
#
|
224
|
+
# `-- themes
|
225
|
+
# `-- default
|
226
|
+
# `-- public
|
227
|
+
# `-- hello_word.html
|
228
|
+
#
|
229
|
+
# GET /hello_word.html => 200 themes/default/public/hello_word.html
|
230
|
+
#
|
231
|
+
# If no match is found, the route handler attempts to match the URI path with a content page
|
232
|
+
# template stored in `settings.content`. If a content page template is found, the handler will:
|
233
|
+
#
|
234
|
+
# * Read the content page into memory and assign it to the `@content_page` instance variable
|
235
|
+
# * Render the content page's view template file (see `Mango::ContentPages`)
|
236
|
+
# * A `RuntimeError` is raised if the view template does not exist within `settings.views`
|
237
|
+
# * Send the rendered page with a 200 HTTP response code and halt execution
|
238
|
+
#
|
239
|
+
# In addition, if a `layout.haml` template exists within `settings.views`, the page's view
|
240
|
+
# template is wrapped within this layout when rendered.
|
241
|
+
#
|
242
|
+
# For example:
|
243
|
+
#
|
244
|
+
# |-- content
|
245
|
+
# | `-- index.haml
|
246
|
+
# `-- themes
|
247
|
+
# `-- default
|
248
|
+
# `-- views
|
249
|
+
# |-- layout.haml
|
250
|
+
# `-- page.haml
|
251
|
+
#
|
252
|
+
# GET /index => 200 content/index.haml +
|
253
|
+
# themes/default/views/page.haml +
|
254
|
+
# themes/default/views/layout.haml
|
255
|
+
#
|
256
|
+
# Finally, if no matches are found, the route handler passes execution to the `NOT_FOUND` error
|
257
|
+
# handler.
|
258
|
+
#
|
259
|
+
get "/*" do |uri_path|
|
260
|
+
render_index_file! uri_path
|
261
|
+
render_content_page! uri_path
|
262
|
+
not_found
|
263
|
+
end
|
264
|
+
|
265
|
+
###############################################################################################
|
266
|
+
|
267
|
+
private
|
268
|
+
|
269
|
+
# Given a URI path, attempts to send an index.html file, if it exists, and halt
|
270
|
+
#
|
271
|
+
# @param [String] uri_path
|
272
|
+
#
|
273
|
+
def render_index_file!(uri_path)
|
274
|
+
return unless uri_path[-1] == "/"
|
275
|
+
|
276
|
+
index_match = File.join(settings.public, "*")
|
277
|
+
index_file_path = build_index_file_path(uri_path)
|
278
|
+
|
279
|
+
return unless File.fnmatch(index_match, index_file_path)
|
280
|
+
return unless File.file?(index_file_path)
|
281
|
+
|
282
|
+
send_file index_file_path
|
283
|
+
end
|
284
|
+
|
285
|
+
# Given a URI path, build a path to a potential index.html file
|
286
|
+
#
|
287
|
+
# @param [String] uri_path
|
288
|
+
# @return [String] The path to a potential index.html file
|
289
|
+
#
|
290
|
+
def build_index_file_path(uri_path)
|
291
|
+
uri_path = File.join(uri_path, "index.html")
|
292
|
+
File.expand_path(uri_path, settings.public)
|
293
|
+
end
|
294
|
+
|
295
|
+
###############################################################################################
|
296
|
+
|
297
|
+
private
|
298
|
+
|
299
|
+
# Given a URI path, attempts to render a content page, if it exists, and halt
|
300
|
+
#
|
301
|
+
# @param [String] uri_path
|
302
|
+
# @raise [RuntimeError] Raised when the content page's view template cannot be found
|
303
|
+
#
|
304
|
+
def render_content_page!(uri_path)
|
305
|
+
content_match = File.join(settings.content, "*")
|
306
|
+
content_page_path = build_content_page_path(uri_path)
|
307
|
+
return unless File.fnmatch(content_match, content_page_path)
|
308
|
+
|
309
|
+
begin
|
310
|
+
@content_page = Mango::ContentPage.find_by_path(content_page_path)
|
311
|
+
rescue Mango::ContentPage::PageNotFound
|
312
|
+
return
|
313
|
+
end
|
314
|
+
|
315
|
+
begin
|
316
|
+
halt haml(@content_page.view)
|
317
|
+
rescue Errno::ENOENT
|
318
|
+
view_path = File.expand_path("#{@content_page.view}.haml", settings.views)
|
319
|
+
raise "Unable to find a view template file -- #{view_path}"
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
# Given a URI path, build a path to a potential content page
|
324
|
+
#
|
325
|
+
# @param [String] uri_path
|
326
|
+
# @return [String] The path to a potential content page
|
327
|
+
#
|
328
|
+
def build_content_page_path(uri_path)
|
329
|
+
uri_path += "index" if uri_path.empty? || uri_path[-1] == "/"
|
330
|
+
File.expand_path(uri_path, settings.content)
|
331
|
+
end
|
332
|
+
|
333
|
+
end
|
334
|
+
end
|