serif 0.5.2 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +58 -21
  4. data/LICENSE +1 -1
  5. data/README.md +11 -13
  6. data/lib/serif.rb +3 -2
  7. data/lib/serif/admin_server.rb +10 -10
  8. data/lib/serif/commands.rb +2 -2
  9. data/lib/serif/config.rb +1 -1
  10. data/lib/serif/content_file.rb +9 -9
  11. data/lib/serif/draft.rb +1 -1
  12. data/lib/serif/errors.rb +1 -1
  13. data/lib/serif/markup_renderer.rb +28 -17
  14. data/lib/serif/post.rb +1 -1
  15. data/lib/serif/server.rb +1 -1
  16. data/lib/serif/site.rb +5 -29
  17. data/rakefile +3 -6
  18. data/serif.gemspec +9 -3
  19. data/statics/assets/js/attachment.js +3 -3
  20. data/statics/skeleton/_config.yml +1 -1
  21. data/statics/skeleton/_layouts/default.html +1 -1
  22. data/statics/skeleton/_templates/archive_page.html +1 -1
  23. data/statics/skeleton/_templates/post.html +1 -1
  24. data/statics/skeleton/archive.html +1 -1
  25. data/statics/skeleton/index.html +1 -1
  26. data/statics/templates/admin/bookmarks.liquid +1 -1
  27. data/statics/templates/admin/edit_draft.liquid +1 -1
  28. data/statics/templates/admin/index.liquid +1 -1
  29. data/statics/templates/admin/layout.liquid +6 -4
  30. data/statics/templates/admin/new_draft.liquid +1 -1
  31. metadata +123 -127
  32. data/test/commands_spec.rb +0 -77
  33. data/test/config_spec.rb +0 -55
  34. data/test/content_file_spec.rb +0 -113
  35. data/test/draft_spec.rb +0 -275
  36. data/test/file_digest_tag_spec.rb +0 -38
  37. data/test/filters_spec.rb +0 -90
  38. data/test/liquid_filter_date_extension_spec.rb +0 -15
  39. data/test/markup_renderer_spec.rb +0 -47
  40. data/test/post_spec.rb +0 -139
  41. data/test/site_dir/_config.yml +0 -18
  42. data/test/site_dir/_drafts/another-sample-draft +0 -3
  43. data/test/site_dir/_drafts/sample-draft +0 -3
  44. data/test/site_dir/_layouts/alt-layout.html +0 -3
  45. data/test/site_dir/_layouts/default.html +0 -8
  46. data/test/site_dir/_posts/2012-01-05-sample-post +0 -4
  47. data/test/site_dir/_posts/2013-01-01-second-post +0 -4
  48. data/test/site_dir/_posts/2013-03-07-post-with-custom-layout +0 -5
  49. data/test/site_dir/_posts/2399-01-01-penultimate-post +0 -4
  50. data/test/site_dir/_posts/2400-01-01-final-post +0 -4
  51. data/test/site_dir/_templates/archive_page.html +0 -9
  52. data/test/site_dir/_templates/post.html +0 -10
  53. data/test/site_dir/archive.html +0 -7
  54. data/test/site_dir/file-digest-test.html +0 -4
  55. data/test/site_dir/index.html +0 -9
  56. data/test/site_dir/page-alt-layout.html +0 -3
  57. data/test/site_dir/page-header-but-no-layout.html +0 -3
  58. data/test/site_dir/test-smarty-filter.html +0 -3
  59. data/test/site_dir/test-stylesheet.css +0 -3
  60. data/test/site_generation_spec.rb +0 -204
  61. data/test/site_spec.rb +0 -189
  62. data/test/test_helper.rb +0 -61
@@ -1,9 +0,0 @@
1
- <h2>Posts</h2>
2
-
3
- <p>There are {{ site.posts.size }} posts:</p>
4
-
5
- <ul>
6
- {% for post in site.posts %}
7
- <li><a href="{{ post.url | escape }}">{{ post.title | escape }}</a> (posted {{ post.created | xmlschema }})</li>
8
- {% endfor %}
9
- </ul>
@@ -1,3 +0,0 @@
1
- layout: alt-layout
2
-
3
- page alt layout
@@ -1,3 +0,0 @@
1
- foo: bar
2
-
3
- file containing headers but no layout option, to test that it still uses the default
@@ -1,3 +0,0 @@
1
- Some content
2
-
3
- {{ "testing's for a " | append: '"' | append: "heading's" | append: '"' | append: " `with code` in it..." | smarty }}
@@ -1,3 +0,0 @@
1
- #foo {
2
- bar: baz;
3
- }
@@ -1,204 +0,0 @@
1
- require "test_helper"
2
-
3
- describe Serif::Site do
4
- subject do
5
- Serif::Site.new(testing_dir)
6
- end
7
-
8
- before(:each) do
9
- FileUtils.rm_rf(testing_dir("_site"))
10
- end
11
-
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
-
19
- it "uses the permalinks in the config file for site generation" do
20
- capture_stdout { subject.generate }
21
- File.exist?(testing_dir("_site/test-blog/sample-post.html")).should be_true
22
- end
23
-
24
- it "reads the layout header for a non-post file and uses the appropriate layout file" do
25
- capture_stdout { subject.generate }
26
-
27
- # check it actually got generated
28
- File.exist?(testing_dir("_site/page-alt-layout.html")).should be_true
29
- File.read("_site/page-alt-layout.html").lines.first.should =~ /<h1.+?>Alternate layout<\/h1>/
30
- end
31
-
32
- it "reads the layout header for a post file and uses the appropriate layout file" do
33
- capture_stdout { subject.generate }
34
-
35
- # check it actually got generated
36
- File.exist?(testing_dir("_site/test-blog/post-with-custom-layout.html")).should be_true
37
- File.read("_site/test-blog/post-with-custom-layout.html").lines.first.should =~ /<h1.+?>Alternate layout<\/h1>/
38
- end
39
-
40
- it "supports a smarty filter" do
41
- capture_stdout { subject.generate }
42
- File.read("_site/test-smarty-filter.html").should =~ /testing&rsquo;s for a &ldquo;heading&rsquo;s&rdquo; `with code` in it&hellip;/
43
- end
44
-
45
- it "correctly handles file_digest calls" do
46
- capture_stdout { subject.generate }
47
-
48
- File.read("_site/file-digest-test.html").strip.should == "f8390232f0c354a871f9ba0ed306163c\n.f8390232f0c354a871f9ba0ed306163c"
49
- end
50
-
51
- it "makes the previous and next posts available" do
52
- capture_stdout { subject.generate }
53
-
54
- contents = File.read("_site/test-blog/sample-post.html")
55
- previous_title = contents[/^Previous post: .+?$/]
56
- next_title = contents[/^Next post: .+?$/]
57
-
58
- previous_title.should be_nil
59
- next_title.should_not be_nil
60
- next_title[/(?<=: ).+/].should == "Second post"
61
-
62
- contents = File.read("_site/test-blog/final-post.html")
63
- previous_title = contents[/Previous post: .+?$/]
64
- next_title = contents[/Next post: .+?$/]
65
-
66
- previous_title.should_not be_nil
67
- next_title.should be_nil
68
- previous_title[/(?<=: ).+/].should == "Penultimate post"
69
- end
70
-
71
- it "sets a draft_preview flag for preview urls" do
72
- preview_flag_pattern = /draftpreviewflagexists/
73
-
74
- capture_stdout { subject.generate }
75
-
76
- d = Serif::Draft.from_slug(subject, "sample-draft")
77
- preview_contents = File.read(testing_dir("_site/#{subject.private_url(d)}.html"))
78
- (preview_contents =~ preview_flag_pattern).should be_true
79
-
80
- # does not exist on live published pages
81
- (File.read(testing_dir("_site/test-blog/second-post.html")) =~ preview_flag_pattern).should be_false
82
- end
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
-
107
- it "creates draft preview files" do
108
- capture_stdout { subject.generate }
109
-
110
- Dir.exist?(testing_dir("_site/drafts")).should be_true
111
- Dir[File.join(testing_dir("_site/drafts/*"))].size.should == subject.drafts.size
112
-
113
- Dir.exist?(testing_dir("_site/drafts/sample-draft")).should be_true
114
- Dir[File.join(testing_dir("_site/drafts/sample-draft"), "*.html")].size.should == 1
115
-
116
- d = Serif::Draft.from_slug(subject, "sample-draft")
117
- subject.private_url(d).should_not be_nil
118
-
119
- # absolute paths
120
- (subject.private_url(d) =~ /\A\/drafts\/#{d.slug}\/.*\z/).should be_true
121
-
122
- # 60 characters long (30 bytes as hex chars)
123
- (subject.private_url(d) =~ /\A\/drafts\/#{d.slug}\/[a-z0-9]{60}\z/).should be_true
124
-
125
- # does not create more than one
126
- capture_stdout { subject.generate }
127
- Dir[File.join(testing_dir("_site/drafts/sample-draft"), "*.html")].size.should == 1
128
- end
129
-
130
- context "for posts with an update: now header" do
131
- around :each do |example|
132
- begin
133
- d = Serif::Draft.new(subject)
134
- d.slug = "post-to-be-auto-updated"
135
- d.title = "Testing title"
136
- d.save("# some content")
137
- d.publish!
138
-
139
- @temporary_post = Serif::Post.new(subject, d.path)
140
- @temporary_post.autoupdate = true
141
- @temporary_post.save
142
-
143
- example.run
144
- ensure
145
- FileUtils.rm(@temporary_post.path)
146
- end
147
- end
148
-
149
- it "sets the updated header to the current time" do
150
- t = Time.now + 30
151
- Timecop.freeze(t) do
152
- capture_stdout { subject.generate }
153
- Serif::Post.from_basename(subject, @temporary_post.basename).updated.to_i.should == t.to_i
154
- end
155
- end
156
- end
157
-
158
- context "for drafts with a publish: now header" do
159
- before :each do
160
- @time = Time.utc(2012, 12, 21, 15, 30, 00)
161
-
162
- draft = Serif::Draft.new(subject)
163
- draft.slug = "post-to-be-published-on-generate"
164
- draft.title = "Some draft title"
165
- draft.autopublish = true
166
- draft.save("some content")
167
-
168
- @post = Serif::Draft.from_slug(subject, draft.slug)
169
- @post.should_not be_nil
170
-
171
- # verifies that the header has actually been written to the file, since
172
- # we round-trip the save and load.
173
- @post.autopublish?.should be_true
174
-
175
- # Site#generate creates a backup of the site directory in /tmp
176
- # and uses a timestamp, which is now fixed across all tests,
177
- # so we have to remove it first.
178
- FileUtils.rm_rf("/tmp/_site.2012-12-21-15-30-00")
179
-
180
- Timecop.freeze(@time)
181
- end
182
-
183
- after :each do
184
- Timecop.return
185
-
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}")])
191
- end
192
-
193
- it "places the file in the published posts folder" do
194
- capture_stdout { subject.generate }
195
- File.exist?(testing_dir("_site/test-blog/#{@post.slug}.html")).should be_true
196
- end
197
-
198
- it "marks the creation time as the current time" do
199
- capture_stdout { subject.generate }
200
- subject.posts.find { |p| p.slug == @post.slug }.created.to_i.should == @time.to_i
201
- end
202
- end
203
- end
204
- end
@@ -1,189 +0,0 @@
1
- require "test_helper"
2
-
3
- describe Serif::Site do
4
- subject do
5
- Serif::Site.new(testing_dir)
6
- end
7
-
8
- describe "#conflicts" do
9
- context "with no arguments" do
10
- it "is nil if there are no conflicts" do
11
- subject.conflicts.should be_nil
12
- end
13
-
14
- it "is a map of url => conflicts_array if there are conflicts" do
15
- d = Serif::Draft.new(subject)
16
- conflicting_post = subject.posts.first
17
- d.slug = conflicting_post.slug
18
- d.title = "Anything you like"
19
- d.save("# Some content")
20
-
21
- # need this to be true
22
- d.url.should == conflicting_post.url
23
-
24
- begin
25
- conflicts = subject.conflicts
26
- conflicts.should_not be_nil
27
- conflicts.class.should == Hash
28
- conflicts.size.should == 1
29
- conflicts.keys.should == [conflicting_post.url]
30
- conflicts[conflicting_post.url].size.should == 2
31
- ensure
32
- FileUtils.rm(d.path)
33
- end
34
- end
35
- end
36
-
37
- context "with an argument given" do
38
- it "is nil if there are no conflicts" do
39
- subject.conflicts(subject.drafts.sample).should be_nil
40
- subject.conflicts(subject.posts.sample).should be_nil
41
-
42
- d = Serif::Draft.new(subject)
43
- subject.conflicts(d).should be_nil
44
- end
45
-
46
- it "is an array of conflicting content if there are conflicts" do
47
- d = Serif::Draft.new(subject)
48
- conflicting_post = subject.posts.first
49
- d.slug = conflicting_post.slug
50
- d.title = "Anything you like"
51
- d.save("# Some content")
52
-
53
- # need this to be true
54
- d.url.should == conflicting_post.url
55
-
56
- begin
57
- conflicts = subject.conflicts(d)
58
- conflicts.should_not be_nil
59
- conflicts.class.should == Array
60
- conflicts.size.should == 2
61
- conflicts.each do |e|
62
- e.url.should == conflicting_post.url
63
- end
64
- ensure
65
- FileUtils.rm(d.path)
66
- end
67
- end
68
- end
69
- end
70
-
71
- describe "#source_directory" do
72
- it "should be sane" do
73
- subject.directory.should == File.join(File.dirname(__FILE__), "site_dir")
74
- end
75
- end
76
-
77
- describe "#posts" do
78
- it "is the number of posts in the site" do
79
- subject.posts.length.should == 5
80
- end
81
- end
82
-
83
- describe "#drafts" do
84
- it "is the number of drafts in the site" do
85
- subject.drafts.length.should == 2
86
- end
87
- end
88
-
89
- describe "#private_url" do
90
- it "returns nil for a draft without an existing file" do
91
- d = double("")
92
- d.stub(:slug) { "foo" }
93
- subject.private_url(d).should be_nil
94
- end
95
- end
96
-
97
- describe "#latest_update_time" do
98
- it "is the latest time that a post was updated" do
99
- subject.latest_update_time.should == Serif::Post.all(subject).max_by { |p| p.updated }.updated
100
- end
101
- end
102
-
103
- describe "#site_path" do
104
- it "should be relative, not absolute" do
105
- p = Pathname.new(subject.site_path("foo"))
106
- p.relative?.should be_true
107
- p.absolute?.should be_false
108
- end
109
-
110
- it "takes a string and prepends _site to that path" do
111
- %w[a b c d e f].each do |e|
112
- subject.site_path(e).should == "_site/#{e}"
113
- end
114
- end
115
- end
116
-
117
- describe "#config" do
118
- it "is a Serif::Config instance" do
119
- subject.config.class.should == Serif::Config
120
- end
121
-
122
- it "should have the permalink format available" do
123
- subject.config.permalink.should_not be_nil
124
- end
125
- end
126
-
127
- describe "#archives" do
128
- it "contains posts given in reverse chronological order" do
129
- archives = subject.archives
130
- archives[:posts].each_cons(2) do |a, b|
131
- (a.created >= b.created).should be_true
132
- end
133
-
134
- archives[:years].each do |year|
135
- year[:posts].each_cons(2) do |a, b|
136
- (a.created >= b.created).should be_true
137
- end
138
-
139
- year[:months].each do |month|
140
- month[:posts].each_cons(2) do |a, b|
141
- (a.created >= b.created).should be_true
142
- end
143
- end
144
- end
145
- end
146
- end
147
-
148
- describe "#to_liquid" do
149
- it "uses the value of #archives without modification" do
150
- subject.should_receive(:archives).once
151
- subject.to_liquid
152
- end
153
- end
154
-
155
- describe "#archive_url_for_date" do
156
- it "uses the archive URL format from the config to construct an archive URL string" do
157
- date = Date.parse("2012-01-02")
158
- subject.archive_url_for_date(date).should == "/test-archive/2012/01"
159
- end
160
- end
161
-
162
- describe "#bypass?" do
163
- it "is false if the filename has a .html extension" do
164
- subject.bypass?("foo.html").should be_false
165
- end
166
-
167
- it "is false if the filename has an .xml extension" do
168
- subject.bypass?("foo.xml").should be_false
169
- end
170
-
171
- it "is true if the filename is neither xml nor html by extension" do
172
- subject.bypass?("foo.css").should be_true
173
- end
174
- end
175
-
176
- describe "#tmp_path" do
177
- it "takes a string and prepends tmp/_site to that path" do
178
- %w[a b c d].each do |e|
179
- subject.tmp_path(e).should == "tmp/_site/#{e}"
180
- end
181
- end
182
-
183
- it "should be relative, not absolute" do
184
- p = Pathname.new(subject.tmp_path("foo"))
185
- p.absolute?.should be_false
186
- p.relative?.should be_true
187
- end
188
- end
189
- end
@@ -1,61 +0,0 @@
1
- require "simplecov"
2
-
3
- # if we're running on Travis, use Coveralls, otherwise
4
- # let us generate SimpleCov output as normal.
5
- if ENV["CI"]
6
- require "coveralls"
7
- SimpleCov.formatter = Coveralls::SimpleCov::Formatter
8
- end
9
-
10
- SimpleCov.start do
11
- add_filter "/test/"
12
- end
13
-
14
- # run tests in production mode so that file digests are enabled
15
- ENV["ENV"] = "production"
16
-
17
- # workaround checking. here before loading our application to ensure
18
- # we aren't testing against our own monkeypatches.
19
-
20
- describe "date 'now' patch" do
21
- # if this test fails, the monkey match on StandardFilters#date can be removed
22
- it "is necessary" do
23
- liquid_filter = Object.new
24
- liquid_filter.extend(Liquid::StandardFilters)
25
- (liquid_filter.date_orig("now", "%Y") rescue "").should_not == Time.now.year.to_s
26
- end
27
- end
28
-
29
- describe "curly quote patch" do
30
- # if this test fails, the workaround for the "markdown" filter can be removed
31
- it "is necessary" do
32
- renderer = Redcarpet::Markdown.new(Serif::MarkupRenderer)
33
- renderer.render("something's here").should_not include("something&rsquo;s here")
34
- end
35
- end
36
-
37
- require "serif"
38
- require "serif/commands"
39
- require "fileutils"
40
- require "pathname"
41
- require "time"
42
- require "date"
43
- require "timecop"
44
-
45
- def testing_dir(path = nil)
46
- full_path = File.join(File.dirname(__FILE__), "site_dir")
47
-
48
- path ? File.join(full_path, path) : full_path
49
- end
50
-
51
- def capture_stdout
52
- begin
53
- $orig_stdout = $stdout
54
- $stdout = StringIO.new
55
- yield
56
- $stdout.rewind
57
- return $stdout.string
58
- ensure
59
- $stdout = $orig_stdout
60
- end
61
- end