noumenon 0.0.2 → 0.0.3
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/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
|