milksteak 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme.md +19 -1
- data/lib/milksteak/cms.rb +18 -3
- data/lib/milksteak/version.rb +1 -1
- data/lib/milksteak.rb +23 -3
- data/lib/models/fragment.rb +5 -0
- data/lib/models/page.rb +10 -65
- data/lib/models/yml_content.rb +73 -0
- data/lib/views/admin.erb +5 -0
- data/lib/views/layouts/admin.erb +103 -4
- data/spec/fixtures/fragments/sample_fragment.yml +5 -0
- data/spec/fixtures/objs/sample_obj.yml +5 -0
- data/spec/fixtures/pages/sample_page.yml +1 -0
- data/spec/lib/milksteak/cms_spec.rb +39 -3
- data/spec/models/fragment_spec.rb +7 -0
- data/spec/models/page_spec.rb +10 -45
- data/spec/models/yml_content_spec.rb +62 -0
- data/spec/spec_helper.rb +4 -1
- metadata +26 -15
data/Readme.md
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
|
1
|
+
Milksteak is a little experiment in tiny-cms-land. My goal with it is to build the minimum structure necessary
|
2
|
+
and keep it as far from anything like rails as possible, with minimum requirements, fast tests, and simple
|
3
|
+
structure. Expect the project to change rather dramatically as I add to it, feel free to fork and do whatever
|
4
|
+
you like, and as always, pull requests are very welcome.
|
5
|
+
|
6
|
+
# Install
|
2
7
|
|
3
8
|
gem install milksteak
|
4
9
|
gem 'milksteak' # if using bundler
|
@@ -35,3 +40,16 @@ text to be editable.
|
|
35
40
|
|
36
41
|
Here's the sidebar content. I can use the {{yml_variables}} and such.
|
37
42
|
|
43
|
+
# Roadmap
|
44
|
+
|
45
|
+
* Blog/News engine
|
46
|
+
* Photo galleries
|
47
|
+
* Flexible collection types for data lists and content types (kinda hard to bullet-point intention here)
|
48
|
+
* Support for storage back-ends rather than YML, if necessary
|
49
|
+
* Tie into Tonic CMS (v3) API
|
50
|
+
* Dynamic page routes (currently pages are treated as content fragments)
|
51
|
+
* ... Contact me with your requests and ideas, or fork and add your own
|
52
|
+
|
53
|
+
# License
|
54
|
+
|
55
|
+
Milksteak is released under the MIT license and is copyright (c) 2012 Bryan Thompson
|
data/lib/milksteak/cms.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Milksteak
|
2
|
-
|
2
|
+
class Cms
|
3
|
+
@@pages = []
|
4
|
+
|
3
5
|
def initialize(app)
|
4
6
|
@app = app
|
5
7
|
end
|
@@ -7,9 +9,22 @@ module Milksteak
|
|
7
9
|
def call(env)
|
8
10
|
dup._call(env)
|
9
11
|
end
|
10
|
-
|
12
|
+
|
13
|
+
def load_pages
|
14
|
+
@@pages = []
|
15
|
+
Milksteak::Page.list.each do |name|
|
16
|
+
name = name.match(/^.+\/(.+)\.yml/)[1]
|
17
|
+
page = Milksteak::Page.load(name, "r")
|
18
|
+
@@pages << page
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def route(url)
|
23
|
+
# TODO
|
24
|
+
end
|
25
|
+
|
11
26
|
def _call(env)
|
12
|
-
puts "OK"
|
27
|
+
#puts "OK"
|
13
28
|
@status, @headers, @response = @app.call(env)
|
14
29
|
[@status, @headers, @response]
|
15
30
|
end
|
data/lib/milksteak/version.rb
CHANGED
data/lib/milksteak.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
require "milksteak/version"
|
2
|
+
require "milksteak/cms"
|
2
3
|
require "sinatra/base"
|
3
4
|
require "models/user"
|
5
|
+
require "models/yml_content"
|
4
6
|
require "models/page"
|
7
|
+
require "models/fragment"
|
5
8
|
require "liquid"
|
6
9
|
require "bluecloth"
|
7
10
|
|
@@ -48,9 +51,26 @@ module Milksteak
|
|
48
51
|
msgs.join
|
49
52
|
end
|
50
53
|
end
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
+
|
55
|
+
before '/ms-admin/?*' do
|
56
|
+
|
57
|
+
# note: it is your responsibility to manage users and login processes. Any
|
58
|
+
# reference milksteak uses to a user will be done through the value stored
|
59
|
+
# in session[:ms_user]. It is best to store a string or integer that you can
|
60
|
+
# use on your own to reference the user. This might change at some point to
|
61
|
+
# allowing you to put a Milksteak::User in this variable with predictable
|
62
|
+
# fields that you could populate on login. That way, we can present user actions
|
63
|
+
# in an easy manner.
|
64
|
+
|
65
|
+
unless session[:ms_user]
|
66
|
+
flash[:error] = "You must be logged in to see this area."
|
67
|
+
redirect "/"
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
get "/ms-admin" do
|
73
|
+
erb "admin", :layout => "admin"
|
54
74
|
end
|
55
75
|
end
|
56
76
|
end
|
data/lib/models/page.rb
CHANGED
@@ -1,73 +1,18 @@
|
|
1
1
|
module Milksteak
|
2
|
-
class Page
|
3
|
-
attr_accessor :
|
2
|
+
class Page < YmlContent
|
3
|
+
attr_accessor :route
|
4
4
|
|
5
|
-
def self.
|
6
|
-
milk_root = Milksteak::Admin.milk_root
|
7
|
-
page_dir = File.join(Milksteak::Admin.milk_root, "pages")
|
8
|
-
FileUtils.mkdir(milk_root) unless File.exist? milk_root
|
9
|
-
FileUtils.mkdir(page_dir) unless File.exist? page_dir
|
10
|
-
Dir.glob("#{page_dir}/*.yml")
|
11
|
-
end
|
5
|
+
def self.folder; "pages"; end
|
12
6
|
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
page_dir = File.join(Milksteak::Admin.milk_root, "pages")
|
17
|
-
FileUtils.mkdir(milk_root) unless File.exist? milk_root
|
18
|
-
FileUtils.mkdir(page_dir) unless File.exist? page_dir
|
19
|
-
|
20
|
-
page_dir = File.join(page_dir, "#{name}.yml")
|
21
|
-
f = File.exist?(page_dir) ? File.open(page_dir, mode) : File.new(page_dir, mode)
|
22
|
-
|
23
|
-
p = self.new
|
24
|
-
p.name = name
|
25
|
-
p.file = f
|
26
|
-
p.read_yaml
|
27
|
-
p
|
28
|
-
end
|
7
|
+
# override write to include validation for :route. If validation
|
8
|
+
# becomes something that is needed on a bigger scale, we'll need
|
9
|
+
# to put this into another method activerecord-style
|
29
10
|
|
30
|
-
# writes to a page. Replaces params and content, doesn't merge.
|
31
11
|
def self.write(name, params = {}, content)
|
32
|
-
|
33
|
-
|
34
|
-
p.content = content
|
35
|
-
p.write_yaml
|
36
|
-
p.file.close
|
37
|
-
p
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.render(name)
|
41
|
-
begin
|
42
|
-
p = self.load(name, "r")
|
43
|
-
rendered = Liquid::Template.parse(p.content).render(p.data)
|
44
|
-
BlueCloth.new(rendered).to_html
|
45
|
-
rescue Errno::ENOENT => e
|
46
|
-
""
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def write_yaml
|
51
|
-
if self.data.empty?
|
52
|
-
self.file.write("---\n")
|
53
|
-
else
|
54
|
-
self.file.write(YAML.dump(self.data))
|
55
|
-
end
|
56
|
-
self.file.write("---\n\n")
|
57
|
-
self.file.write(self.content)
|
58
|
-
end
|
59
|
-
|
60
|
-
def read_yaml
|
61
|
-
self.content = self.file.read
|
62
|
-
begin
|
63
|
-
if self.content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)(.*)/m
|
64
|
-
self.content = $3
|
65
|
-
self.data = YAML.load($1)
|
66
|
-
end
|
67
|
-
rescue => e
|
68
|
-
puts "YAML Exception reading #{name}: #{e.message}"
|
69
|
-
end
|
70
|
-
self.data ||= {}
|
12
|
+
raise NoRouteException unless params["route"]
|
13
|
+
super
|
71
14
|
end
|
72
15
|
end
|
16
|
+
|
17
|
+
class NoRouteException < Exception; end
|
73
18
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Milksteak
|
2
|
+
class YmlContent
|
3
|
+
attr_accessor :name, :file, :data, :content, :output
|
4
|
+
|
5
|
+
def self.list
|
6
|
+
milk_root = Milksteak::Admin.milk_root
|
7
|
+
page_dir = File.join(Milksteak::Admin.milk_root, self.folder)
|
8
|
+
FileUtils.mkdir(milk_root) unless File.exist? milk_root
|
9
|
+
FileUtils.mkdir(page_dir) unless File.exist? page_dir
|
10
|
+
Dir.glob("#{page_dir}/*.yml")
|
11
|
+
end
|
12
|
+
|
13
|
+
# loads a page from yaml, sets data and content attributes, returns a Milksteak::Page
|
14
|
+
def self.load(name, mode = "r")
|
15
|
+
milk_root = Milksteak::Admin.milk_root
|
16
|
+
page_dir = File.join(Milksteak::Admin.milk_root, self.folder)
|
17
|
+
FileUtils.mkdir(milk_root) unless File.exist? milk_root
|
18
|
+
FileUtils.mkdir(page_dir) unless File.exist? page_dir
|
19
|
+
|
20
|
+
page_dir = File.join(page_dir, "#{name}.yml")
|
21
|
+
f = File.exist?(page_dir) ? File.open(page_dir, mode) : File.new(page_dir, mode)
|
22
|
+
|
23
|
+
p = self.new
|
24
|
+
p.name = name
|
25
|
+
p.file = f
|
26
|
+
p.read_yaml
|
27
|
+
p
|
28
|
+
end
|
29
|
+
|
30
|
+
# writes to a page. Replaces params and content, doesn't merge.
|
31
|
+
def self.write(name, params = {}, content)
|
32
|
+
p = self.load(name, "w+")
|
33
|
+
p.data = params
|
34
|
+
p.content = content
|
35
|
+
p.write_yaml
|
36
|
+
p.file.close
|
37
|
+
p
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.render(name)
|
41
|
+
begin
|
42
|
+
p = self.load(name, "r")
|
43
|
+
rendered = Liquid::Template.parse(p.content).render(p.data)
|
44
|
+
BlueCloth.new(rendered).to_html
|
45
|
+
rescue Errno::ENOENT => e
|
46
|
+
""
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def write_yaml
|
51
|
+
if self.data.empty?
|
52
|
+
self.file.write("---\n")
|
53
|
+
else
|
54
|
+
self.file.write(YAML.dump(self.data))
|
55
|
+
end
|
56
|
+
self.file.write("---\n\n")
|
57
|
+
self.file.write(self.content)
|
58
|
+
end
|
59
|
+
|
60
|
+
def read_yaml
|
61
|
+
self.content = self.file.read
|
62
|
+
begin
|
63
|
+
if self.content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)(.*)/m
|
64
|
+
self.content = $3
|
65
|
+
self.data = YAML.load($1)
|
66
|
+
end
|
67
|
+
rescue => e
|
68
|
+
puts "YAML Exception reading #{name}: #{e.message}"
|
69
|
+
end
|
70
|
+
self.data ||= {}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/views/admin.erb
ADDED
data/lib/views/layouts/admin.erb
CHANGED
@@ -1,8 +1,107 @@
|
|
1
|
-
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
2
3
|
<head>
|
3
|
-
<
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<title>ms-admin</title>
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7
|
+
<meta name="description" content="">
|
8
|
+
<meta name="author" content="">
|
9
|
+
|
10
|
+
<script src="/milksteak/js/jquery.js"></script>
|
11
|
+
<script src="/milksteak/js/jquery-ui.min.js"></script>
|
12
|
+
<script src="/milksteak/js/jquery.calendrical.js"></script>
|
13
|
+
<script src="/milksteak/js/moment.min.js"></script>
|
14
|
+
<script src="/milksteak/js/mustache.js"></script>
|
15
|
+
<script src="/milksteak/js/underscore.js"></script>
|
16
|
+
<script src="/milksteak/js/backbone.js"></script>
|
17
|
+
<script src="/milksteak/js/prettify.js"></script>
|
18
|
+
|
19
|
+
<!-- Le styles -->
|
20
|
+
<link href="/milksteak/css/calendrical.css" rel="stylesheet">
|
21
|
+
<link href="/milksteak/css/bootstrap.css" rel="stylesheet">
|
22
|
+
<style type="text/css">
|
23
|
+
body {
|
24
|
+
padding-top: 60px;
|
25
|
+
padding-bottom: 40px;
|
26
|
+
}
|
27
|
+
.sidebar-nav {
|
28
|
+
padding: 9px 0;
|
29
|
+
}
|
30
|
+
th.text_right, td.text_right { text-align: right; }
|
31
|
+
th.text_center, td.text_center { text-align: center; }
|
32
|
+
</style>
|
33
|
+
<link href="/milksteak/css/bootstrap-responsive.css" rel="stylesheet">
|
34
|
+
<link href="/milksteak/css/prettify.css" type="text/css" rel="stylesheet" />
|
35
|
+
<link href="/milksteak/css/style.css" rel="stylesheet">
|
36
|
+
|
37
|
+
|
38
|
+
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
39
|
+
<!--[if lt IE 9]>
|
40
|
+
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
41
|
+
<![endif]-->
|
42
|
+
|
43
|
+
<!-- Le fav and touch icons -->
|
44
|
+
<link rel="shortcut icon" href="images/favicon.ico">
|
45
|
+
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
|
46
|
+
<link rel="apple-touch-icon" sizes="72x72" href="images/apple-touch-icon-72x72.png">
|
47
|
+
<link rel="apple-touch-icon" sizes="114x114" href="images/apple-touch-icon-114x114.png">
|
4
48
|
</head>
|
5
|
-
|
6
|
-
|
49
|
+
|
50
|
+
<body>
|
51
|
+
|
52
|
+
<div class="navbar navbar-fixed-top">
|
53
|
+
<div class="navbar-inner">
|
54
|
+
<div class="container-fluid">
|
55
|
+
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
56
|
+
<span class="icon-bar"></span>
|
57
|
+
</a>
|
58
|
+
<a class="brand" href="#">Milksteak</a>
|
59
|
+
<div class="nav-collapse">
|
60
|
+
<ul class="nav">
|
61
|
+
<li><a href="/merchants">Dashboard</a></li>
|
62
|
+
</ul>
|
63
|
+
<p class="navbar-text pull-right">
|
64
|
+
Log In
|
65
|
+
</p>
|
66
|
+
</div><!--/.nav-collapse -->
|
67
|
+
</div>
|
68
|
+
</div>
|
69
|
+
</div>
|
70
|
+
|
71
|
+
<div class="container-fluid">
|
72
|
+
<div class="row-fluid">
|
73
|
+
<div class="span12">
|
74
|
+
<div class="row-fluid">
|
75
|
+
<%= flash_messages %>
|
76
|
+
<%= yield %>
|
77
|
+
</div>
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
|
81
|
+
<hr>
|
82
|
+
<footer>
|
83
|
+
<p>Milksteak CMS © 2012 Bryan Thompson</p>
|
84
|
+
</footer>
|
85
|
+
|
86
|
+
</div><!--/.fluid-container-->
|
87
|
+
|
88
|
+
<!-- Le javascript
|
89
|
+
================================================== -->
|
90
|
+
<!-- Placed at the end of the document so the pages load faster -->
|
91
|
+
<script src="/milksteak/js/bootstrap-transition.js"></script>
|
92
|
+
<script src="/milksteak/js/bootstrap-alert.js"></script>
|
93
|
+
<script src="/milksteak/js/bootstrap-modal.js"></script>
|
94
|
+
<script src="/milksteak/js/bootstrap-dropdown.js"></script>
|
95
|
+
<script src="/milksteak/js/bootstrap-scrollspy.js"></script>
|
96
|
+
<script src="/milksteak/js/bootstrap-tab.js"></script>
|
97
|
+
<script src="/milksteak/js/bootstrap-tooltip.js"></script>
|
98
|
+
<script src="/milksteak/js/bootstrap-popover.js"></script>
|
99
|
+
<script src="/milksteak/js/bootstrap-button.js"></script>
|
100
|
+
<script src="/milksteak/js/bootstrap-collapse.js"></script>
|
101
|
+
<script src="/milksteak/js/bootstrap-carousel.js"></script>
|
102
|
+
<script src="/milksteak/js/bootstrap-typeahead.js"></script>
|
103
|
+
<script src="/ms-admin/app.js"></script>
|
104
|
+
|
7
105
|
</body>
|
8
106
|
</html>
|
107
|
+
|
@@ -5,8 +5,44 @@ describe Milksteak do
|
|
5
5
|
Milksteak::Admin.milk_root.should_not be_nil
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
context "non-logged-in visitors" do
|
9
|
+
it "should redirect to / from /ms-admin" do
|
10
|
+
get "/ms-admin"
|
11
|
+
last_response.status.should == 302
|
12
|
+
get "/ms-admin/"
|
13
|
+
last_response.status.should == 302
|
14
|
+
end
|
11
15
|
end
|
16
|
+
|
17
|
+
context "logged-in users" do
|
18
|
+
it "should successfuly render /ms-admin" do
|
19
|
+
get "/ms-admin", {}, 'rack.session' => { :ms_user => "bryan-test-user-id" }
|
20
|
+
last_response.status.should == 200
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe Milksteak::Cms do
|
27
|
+
before :all do
|
28
|
+
Milksteak::Cms.class_eval("@@pages").should == []
|
29
|
+
Milksteak::Page.should_receive(:list).and_return ["./spec/fixtures/pages/sample_page.yml"]
|
30
|
+
f = File.open(File.join(File.dirname(__FILE__), "../../fixtures/pages/sample_page.yml"), "r")
|
31
|
+
File.should_receive(:new).with("/tmp/milk_site/pages/sample_page.yml", "r").and_return f
|
32
|
+
@a = Milksteak::Cms.new(Sinatra::Application)
|
33
|
+
@a.load_pages
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should pull list of pages and process routes" do
|
37
|
+
pages = Milksteak::Cms.class_eval("@@pages")
|
38
|
+
pages.length.should == 1
|
39
|
+
pages[0].data["route"].should == "/test-page"
|
40
|
+
end
|
41
|
+
|
42
|
+
pending "should find and route an existing page with an appropriate route" do
|
43
|
+
page = @a.route("/test-page")
|
44
|
+
pages.data["route"].should == "/test-page"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should not find a page for a non-existant route"
|
12
48
|
end
|
data/spec/models/page_spec.rb
CHANGED
@@ -1,58 +1,23 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
2
2
|
|
3
3
|
describe Milksteak::Page do
|
4
|
-
it "should make the page dir if it doesn't exist" do
|
5
|
-
File.stub(:exist?).and_return false
|
6
|
-
FileUtils.should_receive(:mkdir).twice.and_return true
|
7
|
-
Milksteak::Page.list.should be_an Array
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should get list of pages from milk_root/pages" do
|
11
|
-
Milksteak::Page.list.should be_an Array
|
12
|
-
end
|
13
|
-
|
14
|
-
# this utility method is used by the read and write methods as a consistent
|
15
|
-
# way to access yml page documents.
|
16
|
-
it "should load a page into params" do
|
17
|
-
f = File.open(File.join(File.dirname(__FILE__), "../fixtures/pages/sample_page.yml"), "r")
|
18
|
-
f.stub(:save).and_return true
|
19
|
-
File.should_receive(:new).with("/tmp/milk_site/pages/home.yml", "r").and_return f
|
20
|
-
page = Milksteak::Page.load("home", "r")
|
21
|
-
page.should be_a Milksteak::Page
|
22
|
-
page.data.should == { "description" => "This is just a test." }
|
23
|
-
page.content.should == "This is some test content. {{description}}\n"
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should write a page with contents in params" do
|
27
|
-
f = File.new(File.join(File.dirname(__FILE__), "../fixtures/pages/scratch_page.yml"), "w+")
|
28
|
-
File.should_receive(:new).with("/tmp/milk_site/pages/home.yml", "w+").and_return f
|
29
|
-
page = Milksteak::Page.write("home", { "description" => "TEST PAGE"}, "TEST CONTENT")
|
30
|
-
page.data.should == { "description" => "TEST PAGE" }
|
31
|
-
page.content.should == "TEST CONTENT"
|
32
|
-
File.unlink(File.join(File.dirname(__FILE__), "../fixtures/pages/scratch_page.yml"))
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should render page content" do
|
36
|
-
f = File.open(File.join(File.dirname(__FILE__), "../fixtures/pages/sample_page.yml"), "r")
|
37
|
-
File.should_receive(:new).with("/tmp/milk_site/pages/home.yml", "r").and_return f
|
38
|
-
content = Milksteak::Page.render("home")
|
39
|
-
content.should == "<p>This is some test content. This is just a test.</p>"
|
40
|
-
end
|
41
4
|
|
42
|
-
it "should
|
43
|
-
|
44
|
-
|
45
|
-
|
5
|
+
it "should raise errors if trying to save without a route variable" do
|
6
|
+
File.should_not_receive(:new)
|
7
|
+
lambda {
|
8
|
+
Milksteak::Page.write("test", {}, "content")
|
9
|
+
}.should raise_error Milksteak::NoRouteException
|
46
10
|
end
|
47
11
|
|
48
|
-
it "should
|
12
|
+
it "should save with a route" do
|
49
13
|
f = File.new(File.join(File.dirname(__FILE__), "../fixtures/pages/scratch_page.yml"), "w+")
|
50
14
|
File.should_receive(:new).with("/tmp/milk_site/pages/home.yml", "w+").and_return f
|
51
|
-
page = Milksteak::Page.write("home",
|
52
|
-
|
15
|
+
page = Milksteak::Page.write("home",
|
16
|
+
{ "description" => "TEST PAGE", "route" => "/test-page"},
|
17
|
+
"TEST CONTENT")
|
18
|
+
page.data.should == { "description" => "TEST PAGE", "route" => "/test-page" }
|
53
19
|
page.content.should == "TEST CONTENT"
|
54
20
|
File.unlink(File.join(File.dirname(__FILE__), "../fixtures/pages/scratch_page.yml"))
|
55
21
|
end
|
56
22
|
|
57
|
-
it "should route pages using middleware"
|
58
23
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../spec_helper.rb")
|
2
|
+
|
3
|
+
class TestYmlObject < Milksteak::YmlContent
|
4
|
+
def self.folder; "objs"; end
|
5
|
+
end
|
6
|
+
|
7
|
+
describe TestYmlObject do
|
8
|
+
|
9
|
+
it "should make the obj dir if it doesn't exist" do
|
10
|
+
File.stub(:exist?).and_return false
|
11
|
+
FileUtils.should_receive(:mkdir).twice.and_return true
|
12
|
+
TestYmlObject.list.should be_an Array
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should get list of objs from milk_root/objs" do
|
16
|
+
TestYmlObject.list.should be_an Array
|
17
|
+
end
|
18
|
+
|
19
|
+
# this utility method is used by the read and write methods as a consistent
|
20
|
+
# way to access yml obj documents.
|
21
|
+
it "should load a obj into params" do
|
22
|
+
f = File.open(File.join(File.dirname(__FILE__), "../fixtures/objs/sample_obj.yml"), "r")
|
23
|
+
f.stub(:save).and_return true
|
24
|
+
File.should_receive(:new).with("/tmp/milk_site/objs/home.yml", "r").and_return f
|
25
|
+
obj = TestYmlObject.load("home", "r")
|
26
|
+
obj.should be_a TestYmlObject
|
27
|
+
obj.data.should == { "description" => "Test Object" }
|
28
|
+
obj.content.should == "This is a {{description}}\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should write a obj with contents in params" do
|
32
|
+
f = File.new(File.join(File.dirname(__FILE__), "../fixtures/objs/scratch_obj.yml"), "w+")
|
33
|
+
File.should_receive(:new).with("/tmp/milk_site/objs/home.yml", "w+").and_return f
|
34
|
+
obj = TestYmlObject.write("home", { "description" => "TEST PAGE"}, "TEST CONTENT")
|
35
|
+
obj.data.should == { "description" => "TEST PAGE" }
|
36
|
+
obj.content.should == "TEST CONTENT"
|
37
|
+
File.unlink(File.join(File.dirname(__FILE__), "../fixtures/objs/scratch_obj.yml"))
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should render obj content" do
|
41
|
+
f = File.open(File.join(File.dirname(__FILE__), "../fixtures/objs/sample_obj.yml"), "r")
|
42
|
+
File.should_receive(:new).with("/tmp/milk_site/objs/home.yml", "r").and_return f
|
43
|
+
content = TestYmlObject.render("home")
|
44
|
+
content.should == "<p>This is a Test Object</p>"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should return empty string if trying to render a obj that doesn't exist" do
|
48
|
+
FileUtils.stub(:mkdir).and_return true
|
49
|
+
empty = TestYmlObject.render("home")
|
50
|
+
empty.should == ""
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should accept an empty hash" do
|
54
|
+
f = File.new(File.join(File.dirname(__FILE__), "../fixtures/objs/scratch_obj.yml"), "w+")
|
55
|
+
File.should_receive(:new).with("/tmp/milk_site/objs/home.yml", "w+").and_return f
|
56
|
+
obj = TestYmlObject.write("home", {}, "TEST CONTENT")
|
57
|
+
obj.data.should == {}
|
58
|
+
obj.content.should == "TEST CONTENT"
|
59
|
+
File.unlink(File.join(File.dirname(__FILE__), "../fixtures/objs/scratch_obj.yml"))
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: milksteak
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-05-23 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &22354600 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *22354600
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: guard-rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &22305220 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *22305220
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: webmock
|
38
|
-
requirement: &
|
38
|
+
requirement: &22304680 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *22304680
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rack-test
|
49
|
-
requirement: &
|
49
|
+
requirement: &22304080 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *22304080
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: liquid
|
60
|
-
requirement: &
|
60
|
+
requirement: &22303480 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *22303480
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: BlueCloth
|
71
|
-
requirement: &
|
71
|
+
requirement: &22302660 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *22302660
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: sinatra
|
82
|
-
requirement: &
|
82
|
+
requirement: &22301800 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *22301800
|
91
91
|
description: ! 'Super tiny and simple ruby-based cms that uses yml for content '
|
92
92
|
email:
|
93
93
|
- bryan.thompson@firespring.com
|
@@ -105,8 +105,10 @@ files:
|
|
105
105
|
- lib/milksteak.rb
|
106
106
|
- lib/milksteak/cms.rb
|
107
107
|
- lib/milksteak/version.rb
|
108
|
+
- lib/models/fragment.rb
|
108
109
|
- lib/models/page.rb
|
109
110
|
- lib/models/user.rb
|
111
|
+
- lib/models/yml_content.rb
|
110
112
|
- lib/public/milksteak/codemirror2/keymap/emacs.js
|
111
113
|
- lib/public/milksteak/codemirror2/keymap/vim.js
|
112
114
|
- lib/public/milksteak/codemirror2/lib/codemirror.css
|
@@ -435,12 +437,17 @@ files:
|
|
435
437
|
- lib/public/milksteak/wymeditor/skins/twopanels/skin.css
|
436
438
|
- lib/public/milksteak/wymeditor/skins/twopanels/skin.js
|
437
439
|
- lib/public/milksteak/wymeditor/skins/wymeditor_icon.png
|
440
|
+
- lib/views/admin.erb
|
438
441
|
- lib/views/layouts/admin.erb
|
439
442
|
- lib/views/login.erb
|
440
443
|
- milksteak.gemspec
|
444
|
+
- spec/fixtures/fragments/sample_fragment.yml
|
445
|
+
- spec/fixtures/objs/sample_obj.yml
|
441
446
|
- spec/fixtures/pages/sample_page.yml
|
442
447
|
- spec/lib/milksteak/cms_spec.rb
|
448
|
+
- spec/models/fragment_spec.rb
|
443
449
|
- spec/models/page_spec.rb
|
450
|
+
- spec/models/yml_content_spec.rb
|
444
451
|
- spec/spec_helper.rb
|
445
452
|
homepage: ''
|
446
453
|
licenses: []
|
@@ -467,7 +474,11 @@ signing_key:
|
|
467
474
|
specification_version: 3
|
468
475
|
summary: Super tiny and simple ruby-based cms
|
469
476
|
test_files:
|
477
|
+
- spec/fixtures/fragments/sample_fragment.yml
|
478
|
+
- spec/fixtures/objs/sample_obj.yml
|
470
479
|
- spec/fixtures/pages/sample_page.yml
|
471
480
|
- spec/lib/milksteak/cms_spec.rb
|
481
|
+
- spec/models/fragment_spec.rb
|
472
482
|
- spec/models/page_spec.rb
|
483
|
+
- spec/models/yml_content_spec.rb
|
473
484
|
- spec/spec_helper.rb
|