noumenon 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.travis.yml +0 -4
- data/.yardopts +5 -0
- data/Gemfile +1 -3
- data/README.md +57 -80
- data/Rakefile +17 -6
- data/bin/noumenon +6 -0
- data/features/dynamic_template_rendering.feature +107 -0
- data/features/generator/site_generator.feature +25 -0
- data/features/mounted_applications.feature +30 -0
- data/features/static_template_rendering.feature +43 -0
- data/features/step_definitions/asset_steps.rb +7 -0
- data/features/step_definitions/content_steps.rb +7 -0
- data/features/step_definitions/generator_steps.rb +22 -0
- data/features/step_definitions/request_steps.rb +31 -0
- data/features/step_definitions/theme_steps.rb +19 -0
- data/features/support/env.rb +38 -0
- data/features/support/theme/theme.yml +5 -0
- data/features/theme_assets.feature +22 -0
- data/generators/repository/index.yml +3 -0
- data/generators/site/Gemfile +3 -0
- data/generators/site/config.ru +7 -0
- data/generators/theme/assets/style.css +1 -0
- data/generators/theme/layouts/default.nou.html +23 -0
- data/generators/theme/templates/default.nou.html +12 -0
- data/generators/theme/theme.yml +5 -0
- data/lib/noumenon/cli.rb +27 -0
- data/lib/noumenon/core.rb +70 -77
- data/lib/noumenon/repository/file_system.rb +102 -0
- data/lib/noumenon/repository.rb +39 -0
- data/lib/noumenon/spec/example_app.rb +19 -6
- data/lib/noumenon/spec/theme_helpers.rb +66 -0
- data/lib/noumenon/spec.rb +4 -7
- data/lib/noumenon/string_extensions.rb +21 -0
- data/lib/noumenon/template.rb +113 -72
- data/lib/noumenon/theme/assets_middleware.rb +21 -0
- data/lib/noumenon/theme.rb +106 -0
- data/lib/noumenon/version.rb +3 -1
- data/lib/noumenon.rb +68 -100
- data/noumenon.gemspec +13 -9
- data/spec/noumenon/repository/file_system_spec.rb +115 -0
- data/spec/noumenon/repository_spec.rb +40 -0
- data/spec/noumenon/template_spec.rb +9 -7
- data/spec/noumenon/theme_spec.rb +129 -0
- data/spec/noumenon_spec.rb +24 -80
- data/spec/spec_helper.rb +5 -14
- data/spec/support/file_matchers.rb +45 -0
- data/spec/support/templates/basic_template.html +1 -0
- data/spec/{fixtures/themes/example_without_layout → support}/templates/template_with_fields.html +1 -1
- metadata +143 -62
- data/lib/noumenon/configuration.rb +0 -28
- data/lib/noumenon/spec/fixtures.rb +0 -34
- data/spec/fixtures/fixture_specs/test +0 -1
- data/spec/fixtures/missing_application/mounted_app/config.yml +0 -1
- data/spec/fixtures/static_example/directory_with_index/index.yml +0 -1
- data/spec/fixtures/static_example/found.html +0 -1
- data/spec/fixtures/static_example/liquid_example.html +0 -1
- data/spec/fixtures/static_example/mounted_app/config.yml +0 -1
- data/spec/fixtures/static_example/template_with_substitutions.html +0 -1
- data/spec/fixtures/static_example/templates/basic_example.yml +0 -1
- data/spec/fixtures/static_example/templates/with_fields.yml +0 -2
- data/spec/fixtures/themes/example/assets/example.txt +0 -1
- data/spec/fixtures/themes/example/templates/layout.html +0 -3
- data/spec/fixtures/themes/example_without_layout/templates/basic_template.html +0 -1
- data/spec/fixtures/themes/example_without_layout/templates/fields.html +0 -1
- data/spec/fixtures/themes/external_theme/assets/example.txt +0 -1
- data/spec/fixtures/themes/unregistered/lib/unregistered.rb +0 -1
- data/spec/noumenon/config_spec.rb +0 -29
- data/spec/noumenon/core_spec.rb +0 -105
- data/spec/noumenon/spec/example_app_spec.rb +0 -14
- data/spec/noumenon/spec/fixtures_spec.rb +0 -41
- data/spec/noumenon/spec_spec.rb +0 -7
- data/watchr.rb +0 -2
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Noumenon::Repository do
|
4
|
+
describe "initialization" do
|
5
|
+
it "allows access to any provided options in #options" do
|
6
|
+
repo = Noumenon::Repository.new(foo: "bar")
|
7
|
+
repo.options[:foo].should == "bar"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it { should respond_to(:put) }
|
12
|
+
describe "calling #put" do
|
13
|
+
it "raises a NotImplementedError" do
|
14
|
+
lambda { subject.put("foo/bar", "Content") }.should raise_error NotImplementedError
|
15
|
+
end
|
16
|
+
|
17
|
+
it "provides some details in the error message" do
|
18
|
+
begin
|
19
|
+
subject.put("foo/bar", "Content")
|
20
|
+
rescue NotImplementedError => e
|
21
|
+
e.to_s.should == "This repository type does not support updating it's contents."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it { should respond_to(:get) }
|
27
|
+
describe "calling #get" do
|
28
|
+
it "raises a NotImplementedError" do
|
29
|
+
lambda { subject.get("foo/bar") }.should raise_error NotImplementedError
|
30
|
+
end
|
31
|
+
|
32
|
+
it "provides some details in the error message" do
|
33
|
+
begin
|
34
|
+
subject.get("foo/bar")
|
35
|
+
rescue NotImplementedError => e
|
36
|
+
e.to_s.should == "This repository type does not support reading it's contents."
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,20 +1,16 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Noumenon::Template do
|
4
|
-
it { should_not be_nil }
|
5
|
-
|
6
4
|
def template_path(name)
|
7
|
-
|
5
|
+
File.expand_path("../../support/templates/#{name}", __FILE__)
|
8
6
|
end
|
9
7
|
|
10
|
-
|
11
|
-
Noumenon.config.theme = "example_without_layout"
|
12
|
-
end
|
8
|
+
it { should_not be_nil }
|
13
9
|
|
14
10
|
it { should respond_to(:fields) }
|
15
11
|
it { should respond_to(:source) }
|
16
12
|
it { should respond_to(:content) }
|
17
|
-
|
13
|
+
|
18
14
|
describe "loading a template from disk" do
|
19
15
|
it "raises a TemplateNotFoundError if the template does not exist" do
|
20
16
|
lambda { Noumenon::Template.from_file "dummy" }.should raise_error Noumenon::Template::NotFoundError
|
@@ -103,6 +99,12 @@ describe Noumenon::Template do
|
|
103
99
|
content.should =~ %r{<div id="content">This is an example, isn't it lovely.</div>}
|
104
100
|
content.should =~ %r{<p class="byline">Written by Jon Wood.</p>}
|
105
101
|
end
|
102
|
+
|
103
|
+
it "accepts field names as symbols" do
|
104
|
+
content = template.render(title: "Example Page", body: "This is an example.", author: "Jon Wood")
|
105
|
+
|
106
|
+
content.should =~ %r{<h1>Example Page</h1>}
|
107
|
+
end
|
106
108
|
end
|
107
109
|
|
108
110
|
context "when provided with fields that are not specified for the template" do
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
describe Noumenon::Theme do
|
6
|
+
describe "loading from a directory" do
|
7
|
+
context "when the directory does not exist" do
|
8
|
+
it "raises a Theme::NotFoundError" do
|
9
|
+
lambda {
|
10
|
+
Noumenon::Theme.load File.join(File.dirname(__FILE__), "non_existant")
|
11
|
+
}.should raise_error Noumenon::Theme::NotFoundError
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when no theme.yml file exists in the directory" do
|
16
|
+
it "raises a Theme::NotFoundError" do
|
17
|
+
with_temporary_theme(nil) do
|
18
|
+
lambda {
|
19
|
+
Noumenon::Theme.load theme_path
|
20
|
+
}.should raise_error Noumenon::Theme::NotFoundError
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when a theme.yml file exists" do
|
26
|
+
let(:description) do
|
27
|
+
{ "name" => "Example Theme",
|
28
|
+
"author" => "Jon Wood",
|
29
|
+
"email" => "jon@blankpad.net",
|
30
|
+
"copyright" => "Blank Pad Development, 2011",
|
31
|
+
"license" => "MIT" }
|
32
|
+
end
|
33
|
+
|
34
|
+
around(:each) do |example|
|
35
|
+
with_temporary_theme(description) do
|
36
|
+
example.run
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "doesn't raise any errors on load" do
|
41
|
+
lambda {
|
42
|
+
Noumenon::Theme.load theme_path
|
43
|
+
}.should_not raise_error
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns an instance of Noumenon::Theme" do
|
47
|
+
Noumenon::Theme.load(theme_path).should be_instance_of Noumenon::Theme
|
48
|
+
end
|
49
|
+
|
50
|
+
it "registers the theme for use" do
|
51
|
+
theme = Noumenon::Theme.load(theme_path)
|
52
|
+
|
53
|
+
Noumenon::Theme.themes.keys.should include "Example Theme"
|
54
|
+
Noumenon::Theme.themes["Example Theme"].should == theme
|
55
|
+
end
|
56
|
+
|
57
|
+
it "sets the path the theme has been loaded from" do
|
58
|
+
theme = Noumenon::Theme.load theme_path
|
59
|
+
theme.path.should == theme_path
|
60
|
+
end
|
61
|
+
|
62
|
+
%w(name author email copyright license).each do |field|
|
63
|
+
it "reads the #{field} from the theme description" do
|
64
|
+
theme = Noumenon::Theme.load theme_path
|
65
|
+
theme.send(field).should == description[field]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "can load symbolised keys as well" do
|
70
|
+
theme = Noumenon::Theme.new(theme_path, name: "Example")
|
71
|
+
theme.name.should == "Example"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "a loaded theme" do
|
77
|
+
around do |example|
|
78
|
+
with_temporary_theme(name: "Example Theme") do
|
79
|
+
example.run
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
let(:theme) { Noumenon::Theme.load theme_path }
|
84
|
+
|
85
|
+
describe "loading a template" do
|
86
|
+
it "when the template did not exist, it raises Template::NotFoundError" do
|
87
|
+
lambda { theme.template("not_found") }.should raise_error Noumenon::Template::NotFoundError
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when the template did exist" do
|
91
|
+
let(:template) { "<h1>Hello, world!</h1>" }
|
92
|
+
subject do
|
93
|
+
File.open(File.join(theme_path, "templates", "example"), "w") { |f| f.print(template) }
|
94
|
+
theme.template("example")
|
95
|
+
end
|
96
|
+
|
97
|
+
it "returns an instance of Noumenon::Template" do
|
98
|
+
subject.should be_instance_of Noumenon::Template
|
99
|
+
end
|
100
|
+
|
101
|
+
it "loads the correct template" do
|
102
|
+
subject.content.should == "<h1>Hello, world!</h1>"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "loading a layout" do
|
108
|
+
it "when the template did not exist, it raises Template::NotFoundError" do
|
109
|
+
lambda { theme.layout("not_found") }.should raise_error Noumenon::Template::NotFoundError
|
110
|
+
end
|
111
|
+
|
112
|
+
context "when the template did exist" do
|
113
|
+
let(:template) { "<h1>Hello, world!</h1>" }
|
114
|
+
subject do
|
115
|
+
File.open(File.join(theme_path, "layouts", "example"), "w") { |f| f.print(template) }
|
116
|
+
theme.layout("example")
|
117
|
+
end
|
118
|
+
|
119
|
+
it "returns an instance of Noumenon::Template" do
|
120
|
+
subject.should be_instance_of Noumenon::Template
|
121
|
+
end
|
122
|
+
|
123
|
+
it "loads the correct template" do
|
124
|
+
subject.content.should == "<h1>Hello, world!</h1>"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
data/spec/noumenon_spec.rb
CHANGED
@@ -1,99 +1,43 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Noumenon do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
Noumenon.boot
|
8
|
-
end
|
9
|
-
|
10
|
-
describe "setting configuration" do
|
11
|
-
before(:each) do
|
12
|
-
Noumenon.config = nil
|
13
|
-
end
|
14
|
-
|
15
|
-
specify { Noumenon.should respond_to(:configure) }
|
16
|
-
specify { Noumenon.should respond_to(:config) }
|
17
|
-
specify { Noumenon.should respond_to(:config=) }
|
18
|
-
|
19
|
-
it "sets config to the provided object on config=" do
|
20
|
-
config = Noumenon::Configuration.new
|
21
|
-
Noumenon.config = config
|
22
|
-
Noumenon.config.should == config
|
4
|
+
describe "managing the content repository" do
|
5
|
+
it "can be set" do
|
6
|
+
Noumenon.content_repository = Noumenon::Repository.new
|
23
7
|
end
|
24
8
|
|
25
|
-
it "
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
it "yields the config instance if a block is provided" do
|
30
|
-
yielded = false
|
31
|
-
|
32
|
-
config = Noumenon::Configuration.new
|
33
|
-
Noumenon.config = config
|
34
|
-
Noumenon.configure do |c|
|
35
|
-
c.should == config
|
36
|
-
yielded = true
|
37
|
-
end
|
38
|
-
|
39
|
-
yielded.should be_true
|
9
|
+
it "can be retrieved" do
|
10
|
+
repo = Noumenon::Repository.new
|
11
|
+
Noumenon.content_repository = repo
|
12
|
+
Noumenon.content_repository.should == repo
|
40
13
|
end
|
41
14
|
end
|
42
15
|
|
43
|
-
describe "
|
44
|
-
context "
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
last_response.status.should == 200
|
50
|
-
last_response.body.should == "This was served by Noumenon::Spec::ExampleApp"
|
51
|
-
end
|
16
|
+
describe "setting the theme" do
|
17
|
+
context "when assigning with a Theme object" do
|
18
|
+
it "sets the theme directly" do
|
19
|
+
theme = Noumenon::Theme.new("/tmp")
|
20
|
+
Noumenon.theme = theme
|
21
|
+
Noumenon.theme.should == theme
|
52
22
|
end
|
23
|
+
end
|
53
24
|
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
25
|
+
context "when assigning a theme name" do
|
26
|
+
around do |example|
|
27
|
+
with_temporary_theme do
|
28
|
+
example.run
|
67
29
|
end
|
68
30
|
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
31
|
|
87
|
-
it "
|
88
|
-
Noumenon.
|
89
|
-
|
90
|
-
|
32
|
+
it "sets the theme if it has been registered" do
|
33
|
+
Noumenon::Theme.load(theme_path)
|
34
|
+
|
35
|
+
Noumenon.theme = "Example Theme"
|
36
|
+
Noumenon.theme.should == Noumenon::Theme.themes["Example Theme"]
|
91
37
|
end
|
92
38
|
|
93
|
-
it "
|
94
|
-
get "/themes/external_theme/example.txt"
|
39
|
+
it "raises an ArgumentError if it has not been registered" do
|
95
40
|
|
96
|
-
last_response.body.should == fixture("themes/external_theme/assets/example.txt")
|
97
41
|
end
|
98
42
|
end
|
99
43
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,21 +1,12 @@
|
|
1
|
+
# Load anything in spec/support
|
2
|
+
Dir.glob(File.join(File.expand_path("..", __FILE__), "support", "**", "*.rb")).each { |f| require f }
|
3
|
+
|
1
4
|
require 'noumenon'
|
2
|
-
require 'noumenon/spec'
|
3
|
-
require 'rack/test'
|
4
5
|
|
5
6
|
RSpec.configure do |spec|
|
6
|
-
|
7
|
-
spec.include Noumenon::Spec
|
8
|
-
include Noumenon::Spec::Fixtures
|
9
|
-
|
10
|
-
Noumenon::Core.set :environment, :test
|
7
|
+
include Noumenon::Spec::ThemeHelpers
|
11
8
|
|
12
9
|
spec.before(:each) do
|
13
|
-
Noumenon
|
14
|
-
Noumenon.register_theme "example_without_layout", fixture_path("themes/example_without_layout")
|
15
|
-
|
16
|
-
Noumenon.configure do |c|
|
17
|
-
c.content_repository_path = fixture_path("static_example")
|
18
|
-
c.theme = "example"
|
19
|
-
end
|
10
|
+
# Configure Noumenon
|
20
11
|
end
|
21
12
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
RSpec::Matchers.define :create_file do |path|
|
2
|
+
match do |block|
|
3
|
+
block.call
|
4
|
+
File.exist?(path)
|
5
|
+
end
|
6
|
+
|
7
|
+
failure_message do
|
8
|
+
"expected a file to be created at #{File.expand_path(path)}"
|
9
|
+
end
|
10
|
+
|
11
|
+
description do
|
12
|
+
"create a file at #{File.expand_path(path)}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
RSpec::Matchers.define :create_directory do |path|
|
17
|
+
match do |block|
|
18
|
+
block.call
|
19
|
+
File.exist?(path) && File.lstat(path).directory?
|
20
|
+
end
|
21
|
+
|
22
|
+
failure_message do
|
23
|
+
"expected a directory to be created at #{File.expand_path(path)}"
|
24
|
+
end
|
25
|
+
|
26
|
+
description do
|
27
|
+
"create a directory at #{File.expand_path(path)}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
RSpec::Matchers.define :move_file do |paths|
|
32
|
+
match do |block|
|
33
|
+
content = File.read(paths[:from])
|
34
|
+
block.call
|
35
|
+
File.exist?(paths[:to]) && !File.exist?(paths[:from]) && File.read(paths[:to]) == content
|
36
|
+
end
|
37
|
+
|
38
|
+
failure_message do
|
39
|
+
"expected the file at #{File.expand_path(paths[:from])} to move to #{File.expand_path(paths[:to])}"
|
40
|
+
end
|
41
|
+
|
42
|
+
description do
|
43
|
+
"move the file at #{File.expand_path(paths[:from])} to #{File.expand_path(paths[:to])}"
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1>Hello!</h1>
|