serif 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/Gemfile.lock +29 -14
  2. data/README.md +28 -14
  3. data/bin/serif +2 -69
  4. data/lib/serif.rb +1 -0
  5. data/lib/serif/admin_server.rb +55 -26
  6. data/lib/serif/commands.rb +150 -0
  7. data/lib/serif/content_file.rb +4 -0
  8. data/lib/serif/draft.rb +24 -2
  9. data/lib/serif/errors.rb +10 -0
  10. data/lib/serif/post.rb +4 -3
  11. data/lib/serif/site.rb +73 -4
  12. data/rakefile +10 -0
  13. data/serif.gemspec +5 -3
  14. data/statics/skeleton/_layouts/default.html +1 -1
  15. data/statics/templates/admin/bookmarks.liquid +17 -13
  16. data/statics/templates/admin/edit_draft.liquid +1 -1
  17. data/statics/templates/admin/edit_post.liquid +1 -1
  18. data/statics/templates/admin/index.liquid +2 -2
  19. data/statics/templates/admin/layout.liquid +16 -0
  20. data/test/commands_spec.rb +77 -0
  21. data/test/content_file_spec.rb +32 -1
  22. data/test/draft_spec.rb +50 -3
  23. data/test/post_spec.rb +31 -2
  24. data/test/site_dir/_layouts/default.html +2 -0
  25. data/test/site_dir/_site/archive.html +2 -0
  26. data/test/site_dir/_site/drafts/another-sample-draft/{481da12b79709bfa0547fa9b5754c9506fbed29afd0334e07a8c95e76850.html → add25848a94509103cb492c47e3a04b7b2a56299de207155fbffec42dc4b.html} +5 -2
  27. data/test/site_dir/_site/drafts/sample-draft/{a986a62ad5f6edd1fcac3d08f5b461b92bcb667a2af69505230c291d405c.html → 0b6fc164b8534d5d5a9fcfc5c709265d33f1577cd0fe2f4e23042e92f0c1.html} +5 -2
  28. data/test/site_dir/_site/index.html +2 -0
  29. data/test/site_dir/_site/page-header-but-no-layout.html +2 -0
  30. data/test/site_dir/_site/test-archive/2012/11.html +2 -0
  31. data/test/site_dir/_site/test-archive/2012/12.html +2 -0
  32. data/test/site_dir/_site/test-archive/2013/01.html +2 -0
  33. data/test/site_dir/_site/test-archive/2013/03.html +2 -0
  34. data/test/site_dir/_site/test-archive/2399/01.html +2 -0
  35. data/test/site_dir/_site/test-archive/2400/01.html +2 -0
  36. data/test/site_dir/_site/test-blog/final-post.html +4 -1
  37. data/test/site_dir/_site/test-blog/penultimate-post.html +4 -1
  38. data/test/site_dir/_site/test-blog/post-to-be-published-on-generate.html +4 -1
  39. data/test/site_dir/_site/test-blog/post-with-custom-layout.html +1 -0
  40. data/test/site_dir/_site/test-blog/sample-post.html +4 -1
  41. data/test/site_dir/_site/test-blog/second-post.html +4 -1
  42. data/test/site_dir/_site/test-smarty-filter.html +2 -0
  43. data/test/site_dir/_templates/post.html +1 -0
  44. data/test/site_dir/_trash/1364747613-autopublish-draft +5 -0
  45. data/test/site_dir/_trash/{1363633154-test-draft → 1364747613-test-draft} +1 -1
  46. data/test/site_generation_spec.rb +40 -9
  47. data/test/site_spec.rb +63 -0
  48. data/test/test_helper.rb +9 -0
  49. metadata +46 -10
  50. data/test/site_dir/_trash/1363633154-autopublish-draft +0 -5
@@ -5,6 +5,37 @@ describe Serif::ContentFile do
5
5
  Serif::Site.new(testing_dir)
6
6
  end
7
7
 
8
+ describe "#basename" do
9
+ it "is the basename of the path" do
10
+ (subject.drafts + subject.posts).each do |content_file|
11
+ content_file.basename.should == File.basename(content_file.path)
12
+ end
13
+
14
+ draft = Serif::Draft.new(subject)
15
+ draft.slug = "foo"
16
+ draft.title = "foo"
17
+
18
+ # NOTE! Freezing!
19
+ Timecop.freeze(Time.parse("2013-04-03"))
20
+
21
+ draft.save
22
+ draft.publish!
23
+ post = Serif::Post.new(subject, draft.path)
24
+
25
+ begin
26
+ draft.path.should_not be_nil
27
+ post.should_not be_nil
28
+ draft.basename.should == post.basename
29
+
30
+ # NOTE! Time frozen!
31
+ post.basename.should == "2013-04-03-foo"
32
+ ensure
33
+ Timecop.return
34
+ FileUtils.rm(post.path)
35
+ end
36
+ end
37
+ end
38
+
8
39
  describe "#title=" do
9
40
  it "sets the underlying header value to the assigned title" do
10
41
  (subject.drafts + subject.posts).each do |content_file|
@@ -24,7 +55,7 @@ describe Serif::ContentFile do
24
55
  draft.save("# Some content")
25
56
  draft.publish!
26
57
 
27
- post = Serif::Post.from_slug(subject, draft.slug)
58
+ post = Serif::Post.new(subject, draft.path)
28
59
 
29
60
  t = Time.now
30
61
  Timecop.freeze(t + 30) do
@@ -7,6 +7,43 @@ describe Serif::Draft do
7
7
  FileUtils.rm_rf(testing_dir("_trash"))
8
8
  end
9
9
 
10
+ describe "#url" do
11
+ it "uses the current time for its placeholder values" do
12
+ d = D.new(@site)
13
+ d.slug = "my-blar-blar"
14
+ orig_headers = d.headers
15
+ d.stub(:headers) { orig_headers.merge(:permalink => "/foo/:year/:month/:day/:title") }
16
+
17
+ Timecop.freeze(Time.parse("2020-02-09")) do
18
+ d.url.should == "/foo/2020/02/09/my-blar-blar"
19
+ end
20
+ end
21
+
22
+ it "can handle nil slug values" do
23
+ d = D.new(@site)
24
+ d.slug.should be_nil
25
+ orig_headers = d.headers
26
+ d.stub(:headers) { orig_headers.merge(:permalink => "/foo/:year/:month/:day/:title") }
27
+
28
+ Timecop.freeze(Time.parse("2020-02-09")) do
29
+ d.url.should == "/foo/2020/02/09/"
30
+ end
31
+ end
32
+
33
+ it "defaults to the config file's permalink value" do
34
+ d = D.new(@site)
35
+ d.slug = "gablarhgle"
36
+ d.url.should == "/test-blog/gablarhgle"
37
+ end
38
+
39
+ it "uses its permalink header value" do
40
+ d = D.new(@site)
41
+ d.slug = "anything"
42
+ d.stub(:headers) { { :permalink => "testage" } }
43
+ d.url.should == "testage"
44
+ end
45
+ end
46
+
10
47
  describe ".rename" do
11
48
  it "moves the draft to a new file" do
12
49
  draft = D.new(@site)
@@ -86,11 +123,11 @@ describe Serif::Draft do
86
123
  published_path = testing_dir("_posts/#{Date.today.to_s}-#{draft.slug}")
87
124
 
88
125
  begin
89
- @site.generate
126
+ capture_stdout { @site.generate }
90
127
  @site.posts.first.slug.should_not == draft.slug
91
128
  @site.to_liquid["posts"].first.slug.should_not == draft.slug
92
129
  draft.publish!
93
- @site.generate
130
+ capture_stdout { @site.generate }
94
131
  @site.posts.first.slug.should == draft.slug
95
132
  @site.to_liquid["posts"].first.slug.should == draft.slug
96
133
  rescue
@@ -122,7 +159,7 @@ describe Serif::Draft do
122
159
  draft.autopublish?.should be_false
123
160
 
124
161
  # check the actual file doesn't have the header
125
- Serif::Post.from_slug(@site, draft.slug).headers[:publish].should be_nil
162
+ Serif::Post.new(@site, draft.path).headers[:publish].should be_nil
126
163
 
127
164
  draft.delete!
128
165
  end
@@ -186,6 +223,16 @@ describe Serif::Draft do
186
223
  end
187
224
  end
188
225
 
226
+ describe "#to_liquid" do
227
+ it "contains the relevant keys" do
228
+ liq = @site.drafts.sample.to_liquid
229
+
230
+ ["title", "content", "slug", "type", "draft", "published", "url"].each do |e|
231
+ liq.key?(e).should be_true
232
+ end
233
+ end
234
+ end
235
+
189
236
  describe "#save" do
190
237
  it "saves the file to _drafts" do
191
238
  draft = D.new(@site)
@@ -5,7 +5,7 @@ describe Serif::Post do
5
5
  Serif::Site.new(testing_dir)
6
6
  end
7
7
 
8
- before :all do
8
+ before :each do
9
9
  @posts = subject.posts
10
10
  end
11
11
 
@@ -16,7 +16,7 @@ describe Serif::Post do
16
16
  d.title = "Testing title"
17
17
  d.save("# some content")
18
18
  d.publish!
19
- @temporary_post = Serif::Post.from_slug(subject, d.slug)
19
+ @temporary_post = Serif::Post.new(subject, d.path)
20
20
 
21
21
  example.run
22
22
  ensure
@@ -24,6 +24,16 @@ describe Serif::Post do
24
24
  end
25
25
  end
26
26
 
27
+ describe "#from_basename" do
28
+ it "is nil if there is nothing found" do
29
+ Serif::Post.from_basename(subject, "eoijfwoifjweofej").should be_nil
30
+ end
31
+
32
+ it "takes full filename within _posts" do
33
+ Serif::Post.from_basename(subject, @temporary_post.basename).path.should == @temporary_post.path
34
+ end
35
+ end
36
+
27
37
  it "uses the config file's permalink value" do
28
38
  @posts.all? { |p| p.url == "/test-blog/#{p.slug}" }.should be_true
29
39
  end
@@ -107,4 +117,23 @@ describe Serif::Post do
107
117
  @temporary_post.autoupdate?.should be_false
108
118
  end
109
119
  end
120
+
121
+ describe "#to_liquid" do
122
+ it "contains the relevant keys" do
123
+ liq = subject.posts.sample.to_liquid
124
+
125
+ ["title",
126
+ "created",
127
+ "updated",
128
+ "content",
129
+ "slug",
130
+ "url",
131
+ "type",
132
+ "draft",
133
+ "published",
134
+ "basename"].each do |e|
135
+ liq.key?(e).should be_true
136
+ end
137
+ end
138
+ end
110
139
  end
@@ -3,4 +3,6 @@
3
3
  <title>My site: {% if page.title and page.title != empty %}{{ page.title | join:" - " }}{% endif %}</title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+ {% if post_page %}<p>post_page flag set for layout</p>{% endif %}
7
+
6
8
  {{ content }}
@@ -4,6 +4,8 @@
4
4
  <h1>mysite.com</h1>
5
5
 
6
6
 
7
+
8
+
7
9
 
8
10
  <h1>
9
11
  <a href="/test-archive/2400/01">January 2400</a>
@@ -1,14 +1,17 @@
1
1
  <!doctype html>
2
2
  <meta charset="UTF-8">
3
- <title>My site: Draft Preview - another sample draft</title>
3
+ <title>My site: another sample draft</title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+
7
+
6
8
  <p>draftpreviewflagexists</p>
9
+
7
10
  <h2>another sample draft</h2>
8
11
 
9
12
  <p>another-sample-draft</p>
10
13
 
11
14
 
12
- <p><a href="http://twitter.com/share?text=another+sample+draft&amp;url=http%3A%2F%2Fwww.mysite.com">Submit this to Twitter.</p>
15
+ <p><a href="http://twitter.com/share?text=another+sample+draft&amp;url=http%3A%2F%2Fwww.mysite.com%2Ftest-blog%2Fanother-sample-draft">Submit this to Twitter.</p>
13
16
 
14
17
 
@@ -1,14 +1,17 @@
1
1
  <!doctype html>
2
2
  <meta charset="UTF-8">
3
- <title>My site: Draft Preview - Sample draft</title>
3
+ <title>My site: Sample draft</title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+
7
+
6
8
  <p>draftpreviewflagexists</p>
9
+
7
10
  <h2>Sample draft</h2>
8
11
 
9
12
  <p>Just a sample draft.</p>
10
13
 
11
14
 
12
- <p><a href="http://twitter.com/share?text=Sample+draft&amp;url=http%3A%2F%2Fwww.mysite.com">Submit this to Twitter.</p>
15
+ <p><a href="http://twitter.com/share?text=Sample+draft&amp;url=http%3A%2F%2Fwww.mysite.com%2Ftest-blog%2Fsample-draft">Submit this to Twitter.</p>
13
16
 
14
17
 
@@ -3,6 +3,8 @@
3
3
  <title>My site: </title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+
7
+
6
8
  <h2>Posts</h2>
7
9
 
8
10
  <p>There are 6 posts:</p>
@@ -3,4 +3,6 @@
3
3
  <title>My site: </title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+
7
+
6
8
  file containing headers but no layout option, to test that it still uses the default
@@ -3,6 +3,8 @@
3
3
  <title>My site: </title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+
7
+
6
8
  <h1>Nov 2012 (1)</h1>
7
9
 
8
10
  <ul>
@@ -3,6 +3,8 @@
3
3
  <title>My site: </title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+
7
+
6
8
  <h1>Dec 2012 (1)</h1>
7
9
 
8
10
  <ul>
@@ -3,6 +3,8 @@
3
3
  <title>My site: </title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+
7
+
6
8
  <h1>Jan 2013 (1)</h1>
7
9
 
8
10
  <ul>
@@ -3,6 +3,8 @@
3
3
  <title>My site: </title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+
7
+
6
8
  <h1>Mar 2013 (1)</h1>
7
9
 
8
10
  <ul>
@@ -3,6 +3,8 @@
3
3
  <title>My site: </title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+
7
+
6
8
  <h1>Jan 2399 (1)</h1>
7
9
 
8
10
  <ul>
@@ -3,6 +3,8 @@
3
3
  <title>My site: </title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+
7
+
6
8
  <h1>Jan 2400 (1)</h1>
7
9
 
8
10
  <ul>
@@ -1,9 +1,12 @@
1
1
  <!doctype html>
2
2
  <meta charset="UTF-8">
3
- <title>My site: Posts - Final post</title>
3
+ <title>My site: Final post</title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+ <p>post_page flag set for layout</p>
6
7
 
8
+
9
+ <p>post_page flag set for template</p>
7
10
  <h2>Final post</h2>
8
11
 
9
12
  <p>The final post in the blog</p>
@@ -1,9 +1,12 @@
1
1
  <!doctype html>
2
2
  <meta charset="UTF-8">
3
- <title>My site: Posts - Penultimate post</title>
3
+ <title>My site: Penultimate post</title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+ <p>post_page flag set for layout</p>
6
7
 
8
+
9
+ <p>post_page flag set for template</p>
7
10
  <h2>Penultimate post</h2>
8
11
 
9
12
  <p>Penultimate post</p>
@@ -1,9 +1,12 @@
1
1
  <!doctype html>
2
2
  <meta charset="UTF-8">
3
- <title>My site: Posts - Some draft title</title>
3
+ <title>My site: Some draft title</title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+ <p>post_page flag set for layout</p>
6
7
 
8
+
9
+ <p>post_page flag set for template</p>
7
10
  <h2>Some draft title</h2>
8
11
 
9
12
  <p>some content</p>
@@ -1,6 +1,7 @@
1
1
  <h1 id="layout" data-name="alternate-layout">Alternate layout</h1>
2
2
 
3
3
 
4
+ <p>post_page flag set for template</p>
4
5
  <h2>Custom layout</h2>
5
6
 
6
7
  <p>Second post.</p>
@@ -1,9 +1,12 @@
1
1
  <!doctype html>
2
2
  <meta charset="UTF-8">
3
- <title>My site: Posts - Sample post</title>
3
+ <title>My site: Sample post</title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+ <p>post_page flag set for layout</p>
6
7
 
8
+
9
+ <p>post_page flag set for template</p>
7
10
  <h2>Sample post</h2>
8
11
 
9
12
  <p>Just a sample post.</p>
@@ -1,9 +1,12 @@
1
1
  <!doctype html>
2
2
  <meta charset="UTF-8">
3
- <title>My site: Posts - Second post</title>
3
+ <title>My site: Second post</title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+ <p>post_page flag set for layout</p>
6
7
 
8
+
9
+ <p>post_page flag set for template</p>
7
10
  <h2>Second post</h2>
8
11
 
9
12
  <p>Second post.</p>
@@ -3,6 +3,8 @@
3
3
  <title>My site: </title>
4
4
  <h1>mysite.com</h1>
5
5
 
6
+
7
+
6
8
  Some content
7
9
 
8
10
  testing&rsquo;s for a &ldquo;heading&rsquo;s&rdquo; `with code` in it&hellip;
@@ -1,4 +1,5 @@
1
1
  {% if draft_preview %}<p>draftpreviewflagexists</p>{% endif %}
2
+ {% if post_page %}<p>post_page flag set for template</p>{% endif %}
2
3
  <h2>{{ post.title }}</h2>
3
4
 
4
5
  {{ post.content | markdown }}
@@ -0,0 +1,5 @@
1
+ title: Some draft title
2
+ Updated: 2013-03-31T17:33:33+01:00
3
+ Created: 2013-03-31T17:33:33+01:00
4
+
5
+ some content
@@ -1,4 +1,4 @@
1
1
  title: Some draft title
2
- Updated: 2013-03-18T18:59:14+00:00
2
+ Updated: 2013-03-31T17:33:33+01:00
3
3
 
4
4
  some content
@@ -10,6 +10,12 @@ describe Serif::Site do
10
10
  end
11
11
 
12
12
  describe "site generation" do
13
+ it "raises PostConflictError if there are conflicts" do
14
+ # not nil, the value is unimportant
15
+ subject.stub(:conflicts) { [] }
16
+ expect { capture_stdout { subject.generate } }.to raise_error(Serif::PostConflictError)
17
+ end
18
+
13
19
  it "uses the permalinks in the config file for site generation" do
14
20
  capture_stdout { subject.generate }
15
21
  File.exist?(testing_dir("_site/test-blog/sample-post.html")).should be_true
@@ -69,12 +75,35 @@ describe Serif::Site do
69
75
 
70
76
  d = Serif::Draft.from_slug(subject, "sample-draft")
71
77
  preview_contents = File.read(testing_dir("_site/#{subject.private_url(d)}.html"))
72
- preview_contents =~ preview_flag_pattern
78
+ (preview_contents =~ preview_flag_pattern).should be_true
73
79
 
74
80
  # does not exist on live published pages
75
81
  (File.read(testing_dir("_site/test-blog/second-post.html")) =~ preview_flag_pattern).should be_false
76
82
  end
77
83
 
84
+ it "sets a post_page flag for regular posts" do
85
+ capture_stdout { subject.generate }
86
+ d = Serif::Post.from_basename(subject, "2013-01-01-second-post")
87
+ d.should_not be_nil
88
+ contents = File.read(testing_dir("_site#{d.url}.html"))
89
+
90
+ # available to the post layout file
91
+ (contents =~ /post_page flag set for template/).should be_true
92
+
93
+ # available in the layout file itself
94
+ (contents =~ /post_page flag set for layout/).should be_true
95
+
96
+ # not set for regular pages
97
+ (File.read(testing_dir("_site/index.html")) =~ /post_page flag set for template/).should be_false
98
+ (File.read(testing_dir("_site/index.html")) =~ /post_page flag set for layout/).should be_false
99
+
100
+ # not set for drafts
101
+ d = Serif::Draft.from_slug(subject, "sample-draft")
102
+ preview_contents = File.read(testing_dir("_site/#{subject.private_url(d)}.html"))
103
+ (preview_contents =~ /post_page flag set for template/).should be_false
104
+ (preview_contents =~ /post_page flag set for layout/).should be_false
105
+ end
106
+
78
107
  it "creates draft preview files" do
79
108
  capture_stdout { subject.generate }
80
109
 
@@ -107,7 +136,7 @@ describe Serif::Site do
107
136
  d.save("# some content")
108
137
  d.publish!
109
138
 
110
- @temporary_post = Serif::Post.from_slug(subject, d.slug)
139
+ @temporary_post = Serif::Post.new(subject, d.path)
111
140
  @temporary_post.autoupdate = true
112
141
  @temporary_post.save
113
142
 
@@ -121,13 +150,13 @@ describe Serif::Site do
121
150
  t = Time.now + 30
122
151
  Timecop.freeze(t) do
123
152
  capture_stdout { subject.generate }
124
- Serif::Post.from_slug(subject, @temporary_post.slug).updated.to_i.should == t.to_i
153
+ Serif::Post.from_basename(subject, @temporary_post.basename).updated.to_i.should == t.to_i
125
154
  end
126
155
  end
127
156
  end
128
157
 
129
158
  context "for drafts with a publish: now header" do
130
- before :all do
159
+ before :each do
131
160
  @time = Time.utc(2012, 12, 21, 15, 30, 00)
132
161
 
133
162
  draft = Serif::Draft.new(subject)
@@ -151,12 +180,14 @@ describe Serif::Site do
151
180
  Timecop.freeze(@time)
152
181
  end
153
182
 
154
- after :all do
183
+ after :each do
155
184
  Timecop.return
156
185
 
157
- # the generate processes creates its own set of instances, so the
158
- # value of #path here would be stale if we were to call @post.path
159
- FileUtils.rm(Serif::Post.from_slug(subject, @post.slug).path)
186
+ # the generate processes creates its own set of instances, and we're
187
+ # publishing a draft marked as autopublish, so our @post instance
188
+ # has a #path value which is for the draft, not for the newly published
189
+ # post. thus, we need to clobber.
190
+ FileUtils.rm(*Dir[testing_dir("_posts/*-#{@post.slug}")])
160
191
  end
161
192
 
162
193
  it "places the file in the published posts folder" do
@@ -166,7 +197,7 @@ describe Serif::Site do
166
197
 
167
198
  it "marks the creation time as the current time" do
168
199
  capture_stdout { subject.generate }
169
- Serif::Post.from_slug(subject, @post.slug).created.should == @time
200
+ subject.posts.find { |p| p.slug == @post.slug }.created.to_i.should == @time.to_i
170
201
  end
171
202
  end
172
203
  end