noumenon 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +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>
|