noumenon 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +151 -46
- data/lib/noumenon.rb +61 -5
- data/lib/noumenon/configuration.rb +7 -5
- data/lib/noumenon/core.rb +3 -3
- data/lib/noumenon/spec.rb +1 -0
- data/lib/noumenon/spec/example_app.rb +9 -0
- data/lib/noumenon/version.rb +1 -1
- data/spec/fixtures/missing_application/mounted_app/config.yml +1 -0
- data/spec/fixtures/static_example/mounted_app/config.yml +1 -0
- data/spec/fixtures/{static_example_dependencies/themes → themes}/example/assets/example.txt +0 -0
- data/spec/fixtures/{static_example_dependencies/themes/example → themes/example/templates}/layout.html +0 -0
- data/spec/fixtures/{static_example_dependencies/themes/example_without_layout → themes/example_without_layout/templates}/basic_template.html +0 -0
- data/spec/fixtures/{static_example_dependencies/themes/example_without_layout → themes/example_without_layout/templates}/fields.html +0 -0
- data/spec/fixtures/{static_example_dependencies/themes/example_without_layout → themes/example_without_layout/templates}/template_with_fields.html +0 -0
- data/spec/fixtures/themes/external_theme/assets/example.txt +1 -0
- data/spec/fixtures/themes/unregistered/lib/unregistered.rb +1 -0
- data/spec/noumenon/config_spec.rb +8 -8
- data/spec/noumenon/core_spec.rb +3 -3
- data/spec/noumenon/spec/example_app_spec.rb +14 -0
- data/spec/noumenon/template_spec.rb +1 -1
- data/spec/noumenon_spec.rb +58 -19
- data/spec/spec_helper.rb +3 -1
- metadata +24 -12
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 Blank Pad Development
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -13,73 +13,178 @@ editors thats more likely to be a web interface.
|
|
13
13
|
|
14
14
|
## How it Works
|
15
15
|
|
16
|
-
|
16
|
+
A Noumenon site has two fundamental components, a content repository, and a theme.
|
17
|
+
|
18
|
+
### The Content Repository
|
19
|
+
|
20
|
+
The content repository is used to store items of content for the site. By default they're represented by YAML files
|
21
|
+
in a directory tree which should match the URL structure you want to use:
|
17
22
|
|
18
23
|
/
|
19
|
-
-
|
20
|
-
- /index.html
|
24
|
+
- index.yml
|
21
25
|
- /about
|
22
|
-
- /
|
23
|
-
- /
|
26
|
+
- /index.yml
|
27
|
+
- /people.yml
|
28
|
+
- /company.yml
|
24
29
|
- /contact
|
25
|
-
- /config.
|
26
|
-
- /blog
|
27
|
-
- /config.rb
|
28
|
-
- /posts/2011-04-18-an-example-post.md
|
29
|
-
- /posts/2011-04-10-another-example.md
|
30
|
+
- /config.yml
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
In the example above visiting http://example.org/ will render the content in /index.yml, while visiting
|
33
|
+
http://example.org/about/people will render /about/people.yml
|
33
34
|
|
34
|
-
|
35
|
-
domain "example.org"
|
36
|
-
application "git://github.com/noumenon/apps-static"
|
37
|
-
theme "git://github.com/noumenon/themes-example"
|
35
|
+
Each item of content has this format:
|
38
36
|
|
39
|
-
|
40
|
-
|
37
|
+
template "page"
|
38
|
+
title: "People"
|
39
|
+
subtitle: "Our people are what makes us special"
|
40
|
+
body:
|
41
|
+
Here at Enormicorp we believe our people make us a great company.
|
41
42
|
|
42
|
-
|
43
|
-
application "git://github.com/noumenon/apps-contact"
|
44
|
-
contact.email_address "info@example.org"
|
43
|
+
Or at least the ones who's title starts with C and ends in O. Everyone else is just a cog really.
|
45
44
|
|
46
|
-
|
47
|
-
|
45
|
+
When requested a template with a matching name will be loaded from the current theme, and rendered with the fields
|
46
|
+
defined in the content item.
|
48
47
|
|
49
|
-
Finally /blogs/config.rb might look something like this:
|
50
48
|
|
51
|
-
|
52
|
-
blog.comments true
|
49
|
+
### Themes
|
53
50
|
|
54
|
-
|
51
|
+
Themes define how your content should be presented, and can provide templates and assets. A theme will usually come
|
52
|
+
in the form of a Rubygem, either published to rubygems.org, or from some other source which Bundler can access.
|
55
53
|
|
56
|
-
|
54
|
+
For an example, take a look at http://github.com/Noumenon/example_theme
|
57
55
|
|
58
|
-
|
59
|
-
with git as a data store Heroku is not a supported platform for hosting, although I'm sure someone will find a way around that.
|
56
|
+
#### Assets
|
60
57
|
|
61
|
-
|
58
|
+
Assets such as images, stylesheets, and javascripts are placed in the "assets" directory, and are accessible from your
|
59
|
+
application at http://example.org/themes/theme_name/asset.png. The URL structure directly matches the directory structure
|
60
|
+
of your assets directory.
|
62
61
|
|
63
|
-
|
62
|
+
#### Templates
|
64
63
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
The core of a theme is the templates it provides. Each template can list the fields that it supports, and mark some or all
|
65
|
+
of them as being required. Templates also include a Liquid template which is used to transform the provided fields into a
|
66
|
+
web page.
|
67
|
+
|
68
|
+
Templates should be placed in a "templates" sub-directory within your theme, and end with the extension .html
|
69
|
+
|
70
|
+
title:
|
71
|
+
required: true
|
72
|
+
label: "Page title"
|
73
|
+
|
74
|
+
subtitle:
|
75
|
+
required: false
|
76
|
+
|
77
|
+
body:
|
78
|
+
required: true
|
79
|
+
type: "text"
|
80
|
+
---
|
81
|
+
<h1>{{ title }}</h1>
|
82
|
+
{% if subtitile %}
|
83
|
+
<h2>{{ subtitle }}</h2>
|
84
|
+
{% endif %}
|
85
|
+
{{ body }}
|
86
|
+
|
87
|
+
Currently the "label" and "type" attributes on a field are only present for documentation purposes, but they will be used in
|
88
|
+
the future to automatically build the content management interface used by content editors to publish pages, so it's probably
|
89
|
+
worth taking the time to include them.
|
90
|
+
|
91
|
+
If not specified the type defaults to "string", the label to a capitalised version of the name, and required to false.
|
92
|
+
|
93
|
+
Any fields provided to a template which aren't specified will still be available in the Liquid template part.
|
94
|
+
|
95
|
+
### Custom URL handlers
|
96
|
+
|
97
|
+
If part of your site requires something other then rendering a piece of content within a static template then you can use a
|
98
|
+
custom URL handler to provide that part of the site. In this example we'll provide a basic contact form.
|
99
|
+
|
100
|
+
#### Specifying the handler
|
101
|
+
|
102
|
+
Within your content repository create a directory with the same name as the URL you want to mount the application at, and add
|
103
|
+
a file called "config.yml" with the following content:
|
104
|
+
|
105
|
+
application: "Noumenon::Applications::ContactForm"
|
106
|
+
|
107
|
+
This specifies that instead of using the core Noumenon application you want to use the ContactForm application, an example implementation
|
108
|
+
is shown below - usually the application would be provided by a Rubygem or other source, and referenced in your Gemfile.
|
109
|
+
|
110
|
+
#### The ContactForm Handler
|
69
111
|
|
70
|
-
|
71
|
-
|
72
|
-
|
112
|
+
class Noumenon::Applications::ContactForm < Noumenon::Core
|
113
|
+
get '/' do
|
114
|
+
render_template "templates/contact/form.html"
|
115
|
+
end
|
73
116
|
|
74
|
-
|
117
|
+
post '/send' do
|
118
|
+
require 'pony'
|
119
|
+
Pony.send :to => "contact@example.org", :body => params[:body], :from => params[:from]
|
75
120
|
|
76
|
-
|
121
|
+
render_template "templates/contact/thanks.html", "body" => params[:body], "from" => params[:from]
|
122
|
+
end
|
123
|
+
end
|
77
124
|
|
78
|
-
|
79
|
-
if you need the admin section to work then you'll have to host somewhere else, but otherwise, use a config.ru like this, and make
|
80
|
-
sure you have Noumenon in your Gemfile:
|
125
|
+
#### Layouts
|
81
126
|
|
127
|
+
Layouts are used to wrap a piece of content with the overall look and feel of your website, and are provided with a single field
|
128
|
+
"body" containing the rendered content. Currently only one layout per theme is supported, and it should be called "layout.html".
|
129
|
+
|
130
|
+
body:
|
131
|
+
required: true
|
132
|
+
type: "text"
|
133
|
+
---
|
134
|
+
<html>
|
135
|
+
<head>
|
136
|
+
<link rel="stylesheet" href="/themes/example_theme/styles.css">
|
137
|
+
<title>Enormicorp</title>
|
138
|
+
</head>
|
139
|
+
|
140
|
+
<body>
|
141
|
+
<h1>Enormicorp</h1>
|
142
|
+
<nav>
|
143
|
+
<ul>
|
144
|
+
<li><a href="/">Home</a></li>
|
145
|
+
<li><a href="/about">About</a></li>
|
146
|
+
<li><a href="/contact">Contact</a></li>
|
147
|
+
</ul>
|
148
|
+
</nav>
|
149
|
+
|
150
|
+
<section id="content">
|
151
|
+
{{ body }}
|
152
|
+
</section>
|
153
|
+
|
154
|
+
<footer>Copyright © 2011, Enormicorp Plc.</footer>
|
155
|
+
</body>
|
156
|
+
</html>
|
157
|
+
|
158
|
+
## Publishing Your Site
|
159
|
+
|
160
|
+
Currently the quickest way to get a Noumenon site on the internet is using Heroku. See http://github.com/Noumenon/example_site for
|
161
|
+
an example of how to get that working.
|
162
|
+
|
163
|
+
Note that once the admin backend is in place, Heroku may not be supported, and certainly won't be supported when using a filesystem
|
164
|
+
based backend for your content repository.
|
165
|
+
|
166
|
+
### Example config.ru
|
167
|
+
|
168
|
+
If you want to host on your own hardware use a config.ru like this:
|
169
|
+
|
170
|
+
require 'bundler/setup'
|
82
171
|
require 'noumenon'
|
83
|
-
|
84
|
-
|
172
|
+
|
173
|
+
Noumenon.config do |c|
|
174
|
+
c.content_repository_path = "/path/to/content_repository"
|
175
|
+
c.theme = "noumenon-example_theme" # Requires you to have a reference to noumenon-example_theme in your Gemfile.
|
176
|
+
end
|
177
|
+
|
85
178
|
run Noumenon.boot
|
179
|
+
|
180
|
+
## Getting Help and Contributing
|
181
|
+
|
182
|
+
If you're using Noumenon I'd love to know about it, especially if you're having trouble, since my aim is to make creating a site based
|
183
|
+
on Noumenon as simple as possible. The best way to get in touch is to open an issue at http://github.com/Noumenon/noumenon/issues.
|
184
|
+
|
185
|
+
If you'd like to contribute fork this repository, and then submit a pull request when you're done. Please make sure to include some tests
|
186
|
+
so that your feature doesn't get broken in the future.
|
187
|
+
|
188
|
+
## License
|
189
|
+
|
190
|
+
Noumenon is released under the MIT license by Blank Pad Development.
|
data/lib/noumenon.rb
CHANGED
@@ -4,9 +4,29 @@ require 'noumenon/core'
|
|
4
4
|
|
5
5
|
module Noumenon
|
6
6
|
class TemplateNotFoundError < StandardError; end
|
7
|
+
class MissingApplicationError < StandardError; end
|
7
8
|
|
8
9
|
class << self
|
9
10
|
# Returns a configured Noumenon application. Intended for use in a Rack configuration:
|
11
|
+
#
|
12
|
+
# By default the following URL handlers are put in place:
|
13
|
+
#
|
14
|
+
# */themes/#{theme_name}/*
|
15
|
+
#
|
16
|
+
# The assets directory of all installed themes are made accessible so that themes can
|
17
|
+
# bundle stylesheets, javascripts, and other static assets.
|
18
|
+
#
|
19
|
+
# */*
|
20
|
+
#
|
21
|
+
# Anything below / is handled by Noumenon::Core, which will simply load a content item
|
22
|
+
# if it exists, and render it within the specified template.
|
23
|
+
#
|
24
|
+
# *Configuring Custom URL Handlers*
|
25
|
+
#
|
26
|
+
# By placing a file called "config.yml" in a directory you can change the URL handler for
|
27
|
+
# it. The "application" attribute sets the class that will handle that URL, for example:
|
28
|
+
#
|
29
|
+
# application: "Noumenon::Applications::ContactForm"
|
10
30
|
#
|
11
31
|
# Example:
|
12
32
|
#
|
@@ -16,17 +36,41 @@ module Noumenon
|
|
16
36
|
# run Noumenon.boot
|
17
37
|
def boot
|
18
38
|
Rack::Builder.new do
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
39
|
+
Noumenon.themes.each do |name, details|
|
40
|
+
map("/themes/#{name}") { run Rack::File.new(File.join(details[:path], "assets")) }
|
41
|
+
end
|
42
|
+
|
43
|
+
Dir.glob(File.join(Noumenon.config.content_repository_path, "**/config.yml")).each do |path|
|
44
|
+
config = YAML.load(File.read(path))
|
45
|
+
|
46
|
+
if config["application"]
|
47
|
+
begin
|
48
|
+
url = path.gsub(Noumenon.config.content_repository_path, "").split("/")[0..-2].join("/")
|
49
|
+
app = Noumenon.constantize(config["application"]).new
|
50
|
+
|
51
|
+
map(url) { run app }
|
52
|
+
rescue NameError => e
|
53
|
+
raise MissingApplicationError.new("The application #{config["application"]} has not been loaded.")
|
54
|
+
end
|
55
|
+
end
|
24
56
|
end
|
25
57
|
|
26
58
|
map("/") { run Core.new }
|
27
59
|
end
|
28
60
|
end
|
29
61
|
|
62
|
+
# Attempts to convert a string into a constant.
|
63
|
+
#
|
64
|
+
# If the constant could not be found then NameError will be raised.
|
65
|
+
def constantize(name)
|
66
|
+
mod = Module
|
67
|
+
name.split("::").each do |mod_name|
|
68
|
+
mod = mod.const_get(mod_name.to_sym)
|
69
|
+
end
|
70
|
+
|
71
|
+
mod
|
72
|
+
end
|
73
|
+
|
30
74
|
# Provides access to the configuration of this application.
|
31
75
|
#
|
32
76
|
# If passed a block then the current configuration will be yielded in the form
|
@@ -49,5 +93,17 @@ module Noumenon
|
|
49
93
|
def config=(config)
|
50
94
|
@config = config
|
51
95
|
end
|
96
|
+
|
97
|
+
# Returns details of any registered themes.
|
98
|
+
def themes
|
99
|
+
@themes ||= {}
|
100
|
+
end
|
101
|
+
|
102
|
+
# Registers a theme for use by Noumenon.
|
103
|
+
#
|
104
|
+
# Any files in the assets/ directory below the path provided will be accessible from /themes/theme_name.
|
105
|
+
def register_theme(name, path)
|
106
|
+
themes[name] = { :path => path }
|
107
|
+
end
|
52
108
|
end
|
53
109
|
end
|
@@ -6,9 +6,6 @@ module Noumenon
|
|
6
6
|
# The path to load content from.
|
7
7
|
attr_accessor :content_repository_path
|
8
8
|
|
9
|
-
# The path to load any depdencies such as themes and applications from.
|
10
|
-
attr_accessor :dependencies_path
|
11
|
-
|
12
9
|
# The theme to use.
|
13
10
|
attr_accessor :theme
|
14
11
|
|
@@ -16,8 +13,13 @@ module Noumenon
|
|
16
13
|
#
|
17
14
|
# If the theme could not be found under dependencies_path then a ThemeNotFoundError will be raised.
|
18
15
|
def theme=(value)
|
19
|
-
|
20
|
-
|
16
|
+
begin
|
17
|
+
require value.gsub("-", "/")
|
18
|
+
rescue LoadError => e
|
19
|
+
end
|
20
|
+
|
21
|
+
unless Noumenon.themes.key?(value)
|
22
|
+
raise ThemeNotFoundError.new("The theme #{value} has not been registered.")
|
21
23
|
end
|
22
24
|
|
23
25
|
@theme = value
|
data/lib/noumenon/core.rb
CHANGED
@@ -26,7 +26,7 @@ module Noumenon
|
|
26
26
|
|
27
27
|
# Get the path to a file provided by the current theme.
|
28
28
|
def theme_path(path)
|
29
|
-
File.join(
|
29
|
+
File.join(Noumenon.themes[config.theme][:path], path)
|
30
30
|
end
|
31
31
|
|
32
32
|
# Render a template, surrounding it with the theme layout if a theme has been set, and
|
@@ -47,7 +47,7 @@ module Noumenon
|
|
47
47
|
|
48
48
|
if options[:layout]
|
49
49
|
begin
|
50
|
-
body = render_template(theme_path("
|
50
|
+
body = render_template(theme_path("templates/#{options[:layout]}.html"), { 'body' => body }, :layout => false)
|
51
51
|
rescue Noumenon::Template::NotFoundError => ignore_missing_layouts
|
52
52
|
end
|
53
53
|
end
|
@@ -63,7 +63,7 @@ module Noumenon
|
|
63
63
|
content = File.read(content_path(path))
|
64
64
|
item = YAML.load( content )
|
65
65
|
|
66
|
-
[ 200, render_template( theme_path("
|
66
|
+
[ 200, render_template( theme_path("templates/#{item["template"]}.html"), item ) ]
|
67
67
|
end
|
68
68
|
|
69
69
|
# Locate a piece of content in the content repository based on the URL it is being accessed from.
|
data/lib/noumenon/spec.rb
CHANGED
data/lib/noumenon/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
application: "NonExistantApplication"
|
@@ -0,0 +1 @@
|
|
1
|
+
application: "Noumenon::Spec::ExampleApp"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
This is example.txt in the external_theme theme.
|
@@ -0,0 +1 @@
|
|
1
|
+
Noumenon.register_theme "unregistered", File.expand_path("../..", __FILE__)
|
@@ -6,24 +6,24 @@ describe Noumenon::Configuration do
|
|
6
6
|
it { should respond_to(:content_repository_path) }
|
7
7
|
it { should respond_to(:content_repository_path=) }
|
8
8
|
|
9
|
-
it { should respond_to(:dependencies_path) }
|
10
|
-
it { should respond_to(:dependencies_path=) }
|
11
|
-
|
12
9
|
it { should respond_to(:theme) }
|
13
10
|
it { should respond_to(:theme=) }
|
14
11
|
|
15
12
|
describe "setting the theme" do
|
16
|
-
before(:each) do
|
17
|
-
subject.dependencies_path = fixture_path("static_example_dependencies")
|
18
|
-
end
|
19
|
-
|
20
13
|
it "succeeds if the theme exists" do
|
21
14
|
subject.theme = "example"
|
22
15
|
subject.theme.should == "example"
|
23
16
|
end
|
24
17
|
|
25
|
-
it "raises an exception if the theme
|
18
|
+
it "raises an exception if the theme has not been registered" do
|
26
19
|
lambda { subject.theme = "none_existant" }.should raise_error Noumenon::Configuration::ThemeNotFoundError
|
27
20
|
end
|
21
|
+
|
22
|
+
it "automatically requires a theme if it can be found" do
|
23
|
+
$: << fixture_path("themes/unregistered/lib")
|
24
|
+
|
25
|
+
subject.theme = "unregistered"
|
26
|
+
subject.theme.should == "unregistered"
|
27
|
+
end
|
28
28
|
end
|
29
29
|
end
|
data/spec/noumenon/core_spec.rb
CHANGED
@@ -22,7 +22,7 @@ describe Noumenon::Core do
|
|
22
22
|
it { should respond_to(:theme_path) }
|
23
23
|
|
24
24
|
it "can locate a path in the theme directory" do
|
25
|
-
app.theme_path("file").should == "
|
25
|
+
app.theme_path("file").should == fixture_path("themes/example/file")
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -63,7 +63,7 @@ describe Noumenon::Core do
|
|
63
63
|
get "/directory_with_index"
|
64
64
|
|
65
65
|
last_response.should be_ok
|
66
|
-
last_response.body.should == File.read(app.theme_path("basic_template.html"))
|
66
|
+
last_response.body.should == File.read(app.theme_path("templates/basic_template.html"))
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -91,7 +91,7 @@ describe Noumenon::Core do
|
|
91
91
|
get "/templates/basic_example"
|
92
92
|
|
93
93
|
last_response.should be_ok
|
94
|
-
last_response.body.should == File.read(app.theme_path("basic_template.html"))
|
94
|
+
last_response.body.should == File.read(app.theme_path("templates/basic_template.html"))
|
95
95
|
end
|
96
96
|
|
97
97
|
it "makes substitutions as specified in the template" do
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Noumenon::Spec::ExampleApp do
|
4
|
+
it { should_not be_nil }
|
5
|
+
|
6
|
+
def app
|
7
|
+
Noumenon::Spec::ExampleApp.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "returns a simple message on a GET to /" do
|
11
|
+
get "/"
|
12
|
+
last_response.body.should == "This was served by Noumenon::Spec::ExampleApp"
|
13
|
+
end
|
14
|
+
end
|
data/spec/noumenon_spec.rb
CHANGED
@@ -1,31 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Noumenon do
|
4
|
-
before(:each) do
|
5
|
-
Noumenon.config.dependencies_path = fixture_path("static_example_dependencies")
|
6
|
-
end
|
7
|
-
|
8
4
|
specify { Noumenon.should respond_to(:boot) }
|
9
5
|
|
10
6
|
def app
|
11
7
|
Noumenon.boot
|
12
8
|
end
|
13
9
|
|
14
|
-
describe "serving theme assets" do
|
15
|
-
it "serves the asset specified at /themes/theme_name/example.txt if the file exists" do
|
16
|
-
get '/themes/example/example.txt'
|
17
|
-
|
18
|
-
last_response.status.should == 200
|
19
|
-
last_response.body.should == fixture("static_example_dependencies/themes/example/assets/example.txt")
|
20
|
-
end
|
21
|
-
|
22
|
-
it "returns a status of 404 if the file does not exist" do
|
23
|
-
get '/themes/example/not_found.png'
|
24
|
-
|
25
|
-
last_response.status.should == 404
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
10
|
describe "setting configuration" do
|
30
11
|
before(:each) do
|
31
12
|
Noumenon.config = nil
|
@@ -58,4 +39,62 @@ describe Noumenon do
|
|
58
39
|
yielded.should be_true
|
59
40
|
end
|
60
41
|
end
|
42
|
+
|
43
|
+
describe "mounting apps in sub-directories" do
|
44
|
+
context "a config.yml file is present in a sub-directory" do
|
45
|
+
context "and the specified application exists" do
|
46
|
+
it "uses that application to respond to requests at the specified directory" do
|
47
|
+
get "/mounted_app"
|
48
|
+
|
49
|
+
last_response.status.should == 200
|
50
|
+
last_response.body.should == "This was served by Noumenon::Spec::ExampleApp"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "and the specified application does not exist" do
|
55
|
+
it "raises a MissingApplicationError" do
|
56
|
+
Noumenon.config.content_repository_path = fixture_path("missing_application")
|
57
|
+
|
58
|
+
raised = false
|
59
|
+
begin
|
60
|
+
app
|
61
|
+
rescue Noumenon::MissingApplicationError => e
|
62
|
+
raised = true
|
63
|
+
e.to_s.should == "The application NonExistantApplication has not been loaded."
|
64
|
+
end
|
65
|
+
|
66
|
+
raised.should be_true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "themes" do
|
73
|
+
before(:each) do
|
74
|
+
Noumenon.instance_eval { @themes = nil }
|
75
|
+
end
|
76
|
+
|
77
|
+
specify { Noumenon.should respond_to(:register_theme) }
|
78
|
+
specify { Noumenon.should respond_to(:themes) }
|
79
|
+
|
80
|
+
it "defaults the theme list to an empty hash" do
|
81
|
+
Noumenon.themes.should == {}
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "registering a theme" do
|
85
|
+
before(:each) { Noumenon.register_theme("external_theme", fixture_path("themes/external_theme")) }
|
86
|
+
|
87
|
+
it "adds the registered theme to the list of available themes" do
|
88
|
+
Noumenon.themes.should == {
|
89
|
+
"external_theme" => { :path => fixture_path("themes/external_theme") }
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should allow access to the theme's assets from /themes/theme_name/asset_name" do
|
94
|
+
get "/themes/external_theme/example.txt"
|
95
|
+
|
96
|
+
last_response.body.should == fixture("themes/external_theme/assets/example.txt")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
61
100
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -10,9 +10,11 @@ RSpec.configure do |spec|
|
|
10
10
|
Noumenon::Core.set :environment, :test
|
11
11
|
|
12
12
|
spec.before(:each) do
|
13
|
+
Noumenon.register_theme "example", fixture_path("themes/example")
|
14
|
+
Noumenon.register_theme "example_without_layout", fixture_path("themes/example_without_layout")
|
15
|
+
|
13
16
|
Noumenon.configure do |c|
|
14
17
|
c.content_repository_path = fixture_path("static_example")
|
15
|
-
c.dependencies_path = fixture_path("static_example_dependencies")
|
16
18
|
c.theme = "example"
|
17
19
|
end
|
18
20
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: noumenon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.3
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jon Wood
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-04-
|
13
|
+
date: 2011-04-20 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -85,30 +85,37 @@ files:
|
|
85
85
|
- .gitignore
|
86
86
|
- .travis.yml
|
87
87
|
- Gemfile
|
88
|
+
- MIT-LICENSE
|
88
89
|
- README.md
|
89
90
|
- Rakefile
|
90
91
|
- lib/noumenon.rb
|
91
92
|
- lib/noumenon/configuration.rb
|
92
93
|
- lib/noumenon/core.rb
|
93
94
|
- lib/noumenon/spec.rb
|
95
|
+
- lib/noumenon/spec/example_app.rb
|
94
96
|
- lib/noumenon/spec/fixtures.rb
|
95
97
|
- lib/noumenon/template.rb
|
96
98
|
- lib/noumenon/version.rb
|
97
99
|
- noumenon.gemspec
|
98
100
|
- spec/fixtures/fixture_specs/test
|
101
|
+
- spec/fixtures/missing_application/mounted_app/config.yml
|
99
102
|
- spec/fixtures/static_example/directory_with_index/index.yml
|
100
103
|
- spec/fixtures/static_example/found.html
|
101
104
|
- spec/fixtures/static_example/liquid_example.html
|
105
|
+
- spec/fixtures/static_example/mounted_app/config.yml
|
102
106
|
- spec/fixtures/static_example/template_with_substitutions.html
|
103
107
|
- spec/fixtures/static_example/templates/basic_example.yml
|
104
108
|
- spec/fixtures/static_example/templates/with_fields.yml
|
105
|
-
- spec/fixtures/
|
106
|
-
- spec/fixtures/
|
107
|
-
- spec/fixtures/
|
108
|
-
- spec/fixtures/
|
109
|
-
- spec/fixtures/
|
109
|
+
- spec/fixtures/themes/example/assets/example.txt
|
110
|
+
- spec/fixtures/themes/example/templates/layout.html
|
111
|
+
- spec/fixtures/themes/example_without_layout/templates/basic_template.html
|
112
|
+
- spec/fixtures/themes/example_without_layout/templates/fields.html
|
113
|
+
- spec/fixtures/themes/example_without_layout/templates/template_with_fields.html
|
114
|
+
- spec/fixtures/themes/external_theme/assets/example.txt
|
115
|
+
- spec/fixtures/themes/unregistered/lib/unregistered.rb
|
110
116
|
- spec/noumenon/config_spec.rb
|
111
117
|
- spec/noumenon/core_spec.rb
|
118
|
+
- spec/noumenon/spec/example_app_spec.rb
|
112
119
|
- spec/noumenon/spec/fixtures_spec.rb
|
113
120
|
- spec/noumenon/spec_spec.rb
|
114
121
|
- spec/noumenon/template_spec.rb
|
@@ -145,19 +152,24 @@ specification_version: 3
|
|
145
152
|
summary: An content management system backed by Git
|
146
153
|
test_files:
|
147
154
|
- spec/fixtures/fixture_specs/test
|
155
|
+
- spec/fixtures/missing_application/mounted_app/config.yml
|
148
156
|
- spec/fixtures/static_example/directory_with_index/index.yml
|
149
157
|
- spec/fixtures/static_example/found.html
|
150
158
|
- spec/fixtures/static_example/liquid_example.html
|
159
|
+
- spec/fixtures/static_example/mounted_app/config.yml
|
151
160
|
- spec/fixtures/static_example/template_with_substitutions.html
|
152
161
|
- spec/fixtures/static_example/templates/basic_example.yml
|
153
162
|
- spec/fixtures/static_example/templates/with_fields.yml
|
154
|
-
- spec/fixtures/
|
155
|
-
- spec/fixtures/
|
156
|
-
- spec/fixtures/
|
157
|
-
- spec/fixtures/
|
158
|
-
- spec/fixtures/
|
163
|
+
- spec/fixtures/themes/example/assets/example.txt
|
164
|
+
- spec/fixtures/themes/example/templates/layout.html
|
165
|
+
- spec/fixtures/themes/example_without_layout/templates/basic_template.html
|
166
|
+
- spec/fixtures/themes/example_without_layout/templates/fields.html
|
167
|
+
- spec/fixtures/themes/example_without_layout/templates/template_with_fields.html
|
168
|
+
- spec/fixtures/themes/external_theme/assets/example.txt
|
169
|
+
- spec/fixtures/themes/unregistered/lib/unregistered.rb
|
159
170
|
- spec/noumenon/config_spec.rb
|
160
171
|
- spec/noumenon/core_spec.rb
|
172
|
+
- spec/noumenon/spec/example_app_spec.rb
|
161
173
|
- spec/noumenon/spec/fixtures_spec.rb
|
162
174
|
- spec/noumenon/spec_spec.rb
|
163
175
|
- spec/noumenon/template_spec.rb
|