serif 0.4 → 0.5

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.
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