stormy 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +65 -0
- data/README.md +64 -0
- data/Rakefile +4 -0
- data/lib/stormy.rb +34 -0
- data/lib/stormy/caches/base.rb +46 -0
- data/lib/stormy/caches/dummy_cache.rb +12 -0
- data/lib/stormy/caches/file_cache.rb +47 -0
- data/lib/stormy/caches/memory_cache.rb +24 -0
- data/lib/stormy/chunk.rb +63 -0
- data/lib/stormy/content.rb +21 -0
- data/lib/stormy/content_list.rb +18 -0
- data/lib/stormy/engines/base.rb +7 -0
- data/lib/stormy/engines/erb.rb +8 -0
- data/lib/stormy/engines/haml.rb +9 -0
- data/lib/stormy/engines/html.rb +6 -0
- data/lib/stormy/engines/markdown.rb +8 -0
- data/lib/stormy/engines/sass.rb +12 -0
- data/lib/stormy/layout.rb +21 -0
- data/lib/stormy/page.rb +32 -0
- data/lib/stormy/static.rb +20 -0
- data/lib/stormy/stores/base.rb +52 -0
- data/lib/stormy/stores/file_store.rb +70 -0
- data/lib/stormy/template.rb +67 -0
- data/lib/stormy/version.rb +3 -0
- data/lib/stormy_app.rb +40 -0
- data/lib/stormy_server.rb +41 -0
- data/spec/fixtures/dummy_site/config.yml +1 -0
- data/spec/fixtures/dummy_site/content/blog/blog-post-1.md +5 -0
- data/spec/fixtures/dummy_site/content/blog/blog-post-2.md +5 -0
- data/spec/fixtures/dummy_site/layouts/main.haml +2 -0
- data/spec/fixtures/dummy_site/public/assets/storm.jpg +0 -0
- data/spec/fixtures/dummy_site/public/blog.haml +12 -0
- data/spec/fixtures/dummy_site/public/blog_desc.haml +13 -0
- data/spec/fixtures/dummy_site/public/hardcoded_blog_post.haml +12 -0
- data/spec/fixtures/dummy_site/public/missing.haml +1 -0
- data/spec/fixtures/dummy_site/public/pathtest/:permalink.haml +16 -0
- data/spec/fixtures/dummy_site/public/redirecto.haml +1 -0
- data/spec/fixtures/dummy_site/public/redirects/:permalink.haml +1 -0
- data/spec/fixtures/dummy_site/public/subdir/index.haml +1 -0
- data/spec/fixtures/dummy_site/public/tester.haml +4 -0
- data/spec/fixtures/dummy_site/public/tester_invalid_layout.haml +4 -0
- data/spec/fixtures/dummy_site/tester.haml +1 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/stormy/caches/caches_spec.rb +50 -0
- data/spec/stormy/engines/erb_spec.rb +24 -0
- data/spec/stormy/engines/sass_spec.rb +24 -0
- data/spec/stormy/page_spec.rb +73 -0
- data/spec/stormy/stores/file_store_spec.rb +66 -0
- data/spec/stormy_app_spec.rb +37 -0
- data/spec/stormy_server_spec.rb +41 -0
- data/stormy.gemspec +33 -0
- data/tasks/rspec.rake +4 -0
- metadata +263 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
%h1 Missing Page Yo!
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- meta[:redirect] = "/tester"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
= meta[:redirect] = "/new-location/" + meta[:permalink]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Index file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
%h1 Tester
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require "simplecov"
|
|
2
|
+
SimpleCov.start do
|
|
3
|
+
add_filter '/spec/'
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
require "codeclimate-test-reporter"
|
|
7
|
+
CodeClimate::TestReporter.start
|
|
8
|
+
|
|
9
|
+
require 'stormy'
|
|
10
|
+
|
|
11
|
+
Dir[File.expand_path('spec/support/**/*.rb')].each(&method(:require))
|
|
12
|
+
|
|
13
|
+
FIXTURE_ROOT = File.join(File.dirname(__FILE__),"fixtures")
|
|
14
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
shared_examples "a stormy cache" do
|
|
4
|
+
|
|
5
|
+
let(:app) { StormyApp.new(root: FIXTURE_ROOT + "/dummy_site/",
|
|
6
|
+
cache: described_class) }
|
|
7
|
+
|
|
8
|
+
context "#page" do
|
|
9
|
+
|
|
10
|
+
it "stores returns the item in the block" do
|
|
11
|
+
result = app.cache.page("tester") do
|
|
12
|
+
"My Val"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
expect(result).to eq "My Val"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "doesn't call the block after it's stored it in the cache" do
|
|
19
|
+
app.cache.page("tester") do
|
|
20
|
+
"Dummy Val"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
result = app.cache.page("tester") do
|
|
24
|
+
raise "Error"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
expect(result).to eq "Dummy Val"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe Stormy::Caches::MemoryCache do
|
|
34
|
+
it_behaves_like "a stormy cache"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe Stormy::Caches::FileCache do
|
|
38
|
+
it_behaves_like "a stormy cache"
|
|
39
|
+
|
|
40
|
+
it "creates the necessary directory" do
|
|
41
|
+
cache_dir = FIXTURE_ROOT + "/dummy_site/tmp/cache"
|
|
42
|
+
FileUtils.rm_r(cache_dir) rescue nil
|
|
43
|
+
|
|
44
|
+
expect(File.directory?(cache_dir)).to eq false
|
|
45
|
+
StormyApp.new(root: FIXTURE_ROOT + "/dummy_site/",
|
|
46
|
+
cache: described_class)
|
|
47
|
+
|
|
48
|
+
expect(File.directory?(cache_dir)).to eq true
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
describe Stormy::Engines::Erb do
|
|
5
|
+
|
|
6
|
+
let(:app) { StormyApp.new({ root: FIXTURE_ROOT + "/dummy_site/" }) }
|
|
7
|
+
let(:engine) { Stormy::Engines::Erb.new(app) }
|
|
8
|
+
|
|
9
|
+
let(:body) do
|
|
10
|
+
<<-DOC
|
|
11
|
+
The answer is <%= 1+2 %>.
|
|
12
|
+
The word is <%= meta[:title] %>
|
|
13
|
+
DOC
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "#render" do
|
|
17
|
+
it "renders erbs" do
|
|
18
|
+
result = engine.render(body,{ meta: { title: "Yay!" }})
|
|
19
|
+
expect(result).to include "The answer is 3"
|
|
20
|
+
expect(result).to include "The word is Yay!"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
describe Stormy::Engines::Sass do
|
|
5
|
+
|
|
6
|
+
let(:app) { StormyApp.new({ root: FIXTURE_ROOT + "/dummy_site/" }) }
|
|
7
|
+
let(:engine) { Stormy::Engines::Sass.new(app) }
|
|
8
|
+
|
|
9
|
+
let(:body) do
|
|
10
|
+
<<-DOC
|
|
11
|
+
.stuff {
|
|
12
|
+
.interior { color:red; }
|
|
13
|
+
}
|
|
14
|
+
DOC
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context "#render" do
|
|
18
|
+
it "renders sass" do
|
|
19
|
+
result = engine.render(body,{})
|
|
20
|
+
expect(result).to include(".stuff .interior")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Stormy::Page do
|
|
4
|
+
|
|
5
|
+
let!(:app) { StormyApp.new(root: FIXTURE_ROOT + "/dummy_site") }
|
|
6
|
+
|
|
7
|
+
describe "#resolve_content" do
|
|
8
|
+
|
|
9
|
+
it "resolves the content from the blog category for hardcoded content" do
|
|
10
|
+
page = app.page("hardcoded_blog_post", {})
|
|
11
|
+
page.resolve_content
|
|
12
|
+
|
|
13
|
+
expect(page.content[:content][:title]).to eq "Super post"
|
|
14
|
+
expect(page.content[:content][:author]).to eq "Svend Karlson"
|
|
15
|
+
expect(page.content[:content][:body]).to include "This is the content of the blog post yo!"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "resolves content from permalinks" do
|
|
19
|
+
page = app.page("pathtest/blog-post-1", {})
|
|
20
|
+
page.resolve_content
|
|
21
|
+
expect(page.content[:post][:title]).to eq "Super post"
|
|
22
|
+
expect(page.content[:post][:author]).to eq "Svend Karlson"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "resolves a content list" do
|
|
26
|
+
page = app.page("blog")
|
|
27
|
+
page.resolve_content
|
|
28
|
+
expect(page.content[:blog].length).to eq 2
|
|
29
|
+
expect(page.content[:blog][0][:title]).to eq "Super post"
|
|
30
|
+
expect(page.content[:blog][1][:title]).to eq "Super post 2"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "correctly orders a content list" do
|
|
34
|
+
page = app.page("blog_desc")
|
|
35
|
+
page.resolve_content
|
|
36
|
+
expect(page.content[:blog].length).to eq 2
|
|
37
|
+
expect(page.content[:blog][0][:title]).to eq "Super post 2"
|
|
38
|
+
expect(page.content[:blog][1][:title]).to eq "Super post"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe "#render" do
|
|
43
|
+
it "renders the output of a page" do
|
|
44
|
+
page = app.page("tester")
|
|
45
|
+
output = page.render
|
|
46
|
+
expect(output[0]).to eq 200
|
|
47
|
+
expect(output[1]['Content-Type']).to eq "text/html"
|
|
48
|
+
expect(output[2][0]).to include "Tester"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "renders the output of content in a page" do
|
|
52
|
+
page = app.page("blog")
|
|
53
|
+
output = page.render
|
|
54
|
+
expect(output[2][0]).to include "Svend Karlson"
|
|
55
|
+
expect(output[2][0]).to include "Bob Johnson"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "does a redirect if redirect is set in the page" do
|
|
59
|
+
page = app.page("redirecto")
|
|
60
|
+
output = page.render
|
|
61
|
+
expect(output[0]).to eq 301
|
|
62
|
+
expect(output[1]["Location"]).to eq "/tester"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "can dynamicaly set the redirect from a path key" do
|
|
66
|
+
page = app.page("redirects/something-awesome")
|
|
67
|
+
output = page.render
|
|
68
|
+
expect(output[0]).to eq 301
|
|
69
|
+
expect(output[1]["Location"]).to eq "/new-location/something-awesome"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe Stormy::Stores::FileStore do
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
let!(:app) { StormyApp.new(root: FIXTURE_ROOT + "/dummy_site",
|
|
7
|
+
store: Stormy::Stores::FileStore ) }
|
|
8
|
+
let!(:store) { app.store }
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
describe "#lookup_filename" do
|
|
12
|
+
|
|
13
|
+
it "returns a filename even if the extension is missing" do
|
|
14
|
+
file,meta = store.lookup_filename("public","tester")
|
|
15
|
+
expect(file).to include "tester.haml"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "returns nil if we try to force the engine extension" do
|
|
19
|
+
file,meta = store.lookup_filename("public","tester.haml")
|
|
20
|
+
expect(file).to eq nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "returns the index file if the path is a directory" do
|
|
24
|
+
file,meta = store.lookup_filename("public","subdir/")
|
|
25
|
+
expect(file).to include "index.haml"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "returns the index file without the trailing slash" do
|
|
29
|
+
file,meta = store.lookup_filename("public","subdir")
|
|
30
|
+
expect(file).to include "index.haml"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "returns a file with path metadata" do
|
|
34
|
+
file,meta = store.lookup_filename("public","pathtest/this-is-a-test")
|
|
35
|
+
expect(file).to include ":permalink.haml"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
describe "#page" do
|
|
41
|
+
it "returns a valid page in public and extracts the meta data" do
|
|
42
|
+
details = store.page("tester")
|
|
43
|
+
expect(details[:path]).to include("tester.haml")
|
|
44
|
+
expect(details[:title]).to eq "The Testerama"
|
|
45
|
+
expect(details[:key]).to eq "tester"
|
|
46
|
+
expect(details[:body]).to include "Tester"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "returns a segmented path with the valid meta data" do
|
|
50
|
+
details = store.page("pathtest/this-is-a-test")
|
|
51
|
+
expect(details[:path]).to include("permalink.haml")
|
|
52
|
+
expect(details[:body]).to include "some random body copy"
|
|
53
|
+
expect(details[:permalink]).to eq "this-is-a-test"
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "#content" do
|
|
58
|
+
it "returns a pieces of content" do
|
|
59
|
+
details = store.content("blog","blog-post-1")
|
|
60
|
+
expect(details[:title]).to eq "Super post"
|
|
61
|
+
expect(details[:author]).to eq "Svend Karlson"
|
|
62
|
+
expect(details[:key]).to eq "blog-post-1"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe StormyApp do
|
|
4
|
+
|
|
5
|
+
context "options" do
|
|
6
|
+
|
|
7
|
+
it "raises an error without a root option set" do
|
|
8
|
+
expect do
|
|
9
|
+
StormyApp.new({})
|
|
10
|
+
end.to raise_error
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "with root set" do
|
|
15
|
+
let(:app) { StormyApp.new(root: FIXTURE_ROOT + "/dummy_site/") }
|
|
16
|
+
|
|
17
|
+
it "sets the root with a root set" do
|
|
18
|
+
app = StormyApp.new(root: "/dummy_site")
|
|
19
|
+
expect(app.root).to eq "/dummy_site"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "creates a dummy cache by default" do
|
|
23
|
+
expect(app.cache).to be_instance_of Stormy::Caches::DummyCache
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "creates a file store by default" do
|
|
27
|
+
expect(app.store).to be_instance_of Stormy::Stores::FileStore
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "loads the defaults.yml file" do
|
|
31
|
+
expect(app.defaults[:layout]).to eq "main"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe StormyServer do
|
|
4
|
+
|
|
5
|
+
let(:server) { StormyServer.new(root: FIXTURE_ROOT + "/dummy_site/") }
|
|
6
|
+
|
|
7
|
+
describe "#call" do
|
|
8
|
+
|
|
9
|
+
it "returns 404 with an invalid page" do
|
|
10
|
+
result = server.call("PATH_INFO" => "/afdsa")
|
|
11
|
+
expect(result[0]).to eq 404
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "returns a 200 with a valid page and valid layout" do
|
|
15
|
+
expect {
|
|
16
|
+
server.call("PATH_INFO" => "/tester_invalid_layout")
|
|
17
|
+
}. to raise_error
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "returns a 200 with a valid page and valid layout" do
|
|
21
|
+
result = server.call("PATH_INFO" => "/tester")
|
|
22
|
+
expect(result[0]).to eq 200
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "returns an image if it's an asset" do
|
|
26
|
+
result = server.call("PATH_INFO" => "/assets/storm.jpg")
|
|
27
|
+
expect(result[0]).to eq 200
|
|
28
|
+
expect(result[1]["Content-Type"]).to eq "image/jpeg"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "renders a custom 404 page" do
|
|
32
|
+
custom_server = StormyServer.new(root: FIXTURE_ROOT + "/dummy_site/",
|
|
33
|
+
page_not_found: "/missing")
|
|
34
|
+
result = custom_server.call("PATH_INFO" => "/asgddasgasgsafd")
|
|
35
|
+
expect(result[0]).to eq 404
|
|
36
|
+
expect(result[2][0]).to include "Missing Page Yo!"
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
data/stormy.gemspec
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'stormy/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "stormy"
|
|
8
|
+
spec.version = Stormy::VERSION
|
|
9
|
+
spec.authors = ["Pascal Rettig"]
|
|
10
|
+
spec.email = ["pascal@cykod.com"]
|
|
11
|
+
spec.summary = %q{Minimal Static CMS}
|
|
12
|
+
spec.description = %q{Still Minimal}
|
|
13
|
+
spec.homepage = ""
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
|
22
|
+
spec.add_development_dependency "rake"
|
|
23
|
+
spec.add_development_dependency 'rspec'
|
|
24
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
spec.add_dependency "rack"
|
|
28
|
+
spec.add_dependency "tilt"
|
|
29
|
+
spec.add_dependency "haml"
|
|
30
|
+
spec.add_dependency "kramdown"
|
|
31
|
+
spec.add_dependency "sass"
|
|
32
|
+
spec.add_dependency "activesupport"
|
|
33
|
+
end
|