monad 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.
Files changed (143) hide show
  1. data/CONTRIBUTING.md +68 -0
  2. data/Gemfile +2 -0
  3. data/LICENSE +21 -0
  4. data/README.md +88 -0
  5. data/Rakefile +136 -0
  6. data/bin/monad +102 -0
  7. data/cucumber.yml +3 -0
  8. data/features/create_sites.feature +112 -0
  9. data/features/data_sources.feature +76 -0
  10. data/features/drafts.feature +25 -0
  11. data/features/embed_filters.feature +60 -0
  12. data/features/markdown.feature +30 -0
  13. data/features/pagination.feature +54 -0
  14. data/features/permalinks.feature +65 -0
  15. data/features/post_data.feature +214 -0
  16. data/features/site_configuration.feature +206 -0
  17. data/features/site_data.feature +101 -0
  18. data/features/step_definitions/monad_steps.rb +175 -0
  19. data/features/support/env.rb +25 -0
  20. data/lib/monad.rb +90 -0
  21. data/lib/monad/command.rb +27 -0
  22. data/lib/monad/commands/build.rb +64 -0
  23. data/lib/monad/commands/doctor.rb +29 -0
  24. data/lib/monad/commands/new.rb +50 -0
  25. data/lib/monad/commands/serve.rb +33 -0
  26. data/lib/monad/configuration.rb +183 -0
  27. data/lib/monad/converter.rb +48 -0
  28. data/lib/monad/converters/identity.rb +21 -0
  29. data/lib/monad/converters/markdown.rb +43 -0
  30. data/lib/monad/converters/markdown/kramdown_parser.rb +44 -0
  31. data/lib/monad/converters/markdown/maruku_parser.rb +47 -0
  32. data/lib/monad/converters/markdown/rdiscount_parser.rb +35 -0
  33. data/lib/monad/converters/markdown/redcarpet_parser.rb +70 -0
  34. data/lib/monad/converters/textile.rb +50 -0
  35. data/lib/monad/convertible.rb +152 -0
  36. data/lib/monad/core_ext.rb +68 -0
  37. data/lib/monad/deprecator.rb +32 -0
  38. data/lib/monad/draft.rb +35 -0
  39. data/lib/monad/drivers/json_driver.rb +39 -0
  40. data/lib/monad/drivers/yaml_driver.rb +23 -0
  41. data/lib/monad/errors.rb +4 -0
  42. data/lib/monad/filters.rb +154 -0
  43. data/lib/monad/generator.rb +4 -0
  44. data/lib/monad/generators/pagination.rb +143 -0
  45. data/lib/monad/layout.rb +42 -0
  46. data/lib/monad/logger.rb +54 -0
  47. data/lib/monad/mime.types +85 -0
  48. data/lib/monad/page.rb +163 -0
  49. data/lib/monad/plugin.rb +75 -0
  50. data/lib/monad/post.rb +377 -0
  51. data/lib/monad/site.rb +455 -0
  52. data/lib/monad/static_file.rb +70 -0
  53. data/lib/monad/tags/gist.rb +30 -0
  54. data/lib/monad/tags/highlight.rb +85 -0
  55. data/lib/monad/tags/include.rb +37 -0
  56. data/lib/monad/tags/post_url.rb +61 -0
  57. data/lib/site_template/.gitignore +1 -0
  58. data/lib/site_template/_config.yml +2 -0
  59. data/lib/site_template/_layouts/default.html +46 -0
  60. data/lib/site_template/_layouts/post.html +9 -0
  61. data/lib/site_template/_posts/0000-00-00-welcome-to-monad.markdown.erb +24 -0
  62. data/lib/site_template/css/main.css +165 -0
  63. data/lib/site_template/css/syntax.css +60 -0
  64. data/lib/site_template/index.html +13 -0
  65. data/monad.gemspec +197 -0
  66. data/script/bootstrap +2 -0
  67. data/test/fixtures/broken_front_matter1.erb +5 -0
  68. data/test/fixtures/broken_front_matter2.erb +4 -0
  69. data/test/fixtures/broken_front_matter3.erb +7 -0
  70. data/test/fixtures/exploit_front_matter.erb +4 -0
  71. data/test/fixtures/front_matter.erb +4 -0
  72. data/test/fixtures/members.yaml +7 -0
  73. data/test/helper.rb +62 -0
  74. data/test/source/.htaccess +8 -0
  75. data/test/source/_includes/sig.markdown +3 -0
  76. data/test/source/_layouts/default.html +27 -0
  77. data/test/source/_layouts/simple.html +1 -0
  78. data/test/source/_plugins/dummy.rb +8 -0
  79. data/test/source/_posts/2008-02-02-not-published.textile +8 -0
  80. data/test/source/_posts/2008-02-02-published.textile +8 -0
  81. data/test/source/_posts/2008-10-18-foo-bar.textile +8 -0
  82. data/test/source/_posts/2008-11-21-complex.textile +8 -0
  83. data/test/source/_posts/2008-12-03-permalinked-post.textile +9 -0
  84. data/test/source/_posts/2008-12-13-include.markdown +8 -0
  85. data/test/source/_posts/2009-01-27-array-categories.textile +10 -0
  86. data/test/source/_posts/2009-01-27-categories.textile +7 -0
  87. data/test/source/_posts/2009-01-27-category.textile +7 -0
  88. data/test/source/_posts/2009-01-27-empty-categories.textile +7 -0
  89. data/test/source/_posts/2009-01-27-empty-category.textile +7 -0
  90. data/test/source/_posts/2009-03-12-hash-#1.markdown +6 -0
  91. data/test/source/_posts/2009-05-18-empty-tag.textile +6 -0
  92. data/test/source/_posts/2009-05-18-empty-tags.textile +6 -0
  93. data/test/source/_posts/2009-05-18-tag.textile +6 -0
  94. data/test/source/_posts/2009-05-18-tags.textile +9 -0
  95. data/test/source/_posts/2009-06-22-empty-yaml.textile +3 -0
  96. data/test/source/_posts/2009-06-22-no-yaml.textile +1 -0
  97. data/test/source/_posts/2010-01-08-triple-dash.markdown +5 -0
  98. data/test/source/_posts/2010-01-09-date-override.textile +7 -0
  99. data/test/source/_posts/2010-01-09-time-override.textile +7 -0
  100. data/test/source/_posts/2010-01-09-timezone-override.textile +7 -0
  101. data/test/source/_posts/2010-01-16-override-data.textile +4 -0
  102. data/test/source/_posts/2011-04-12-md-extension.md +7 -0
  103. data/test/source/_posts/2011-04-12-text-extension.text +0 -0
  104. data/test/source/_posts/2013-01-02-post-excerpt.markdown +14 -0
  105. data/test/source/_posts/2013-01-12-nil-layout.textile +6 -0
  106. data/test/source/_posts/2013-01-12-no-layout.textile +5 -0
  107. data/test/source/_posts/2013-03-19-not-a-post.markdown/.gitkeep +0 -0
  108. data/test/source/_posts/2013-04-11-custom-excerpt.markdown +10 -0
  109. data/test/source/_posts/2013-05-10-number-category.textile +7 -0
  110. data/test/source/_posts/es/2008-11-21-nested.textile +8 -0
  111. data/test/source/about.html +6 -0
  112. data/test/source/category/_posts/2008-9-23-categories.textile +6 -0
  113. data/test/source/contacts.html +5 -0
  114. data/test/source/contacts/bar.html +5 -0
  115. data/test/source/contacts/index.html +5 -0
  116. data/test/source/css/screen.css +76 -0
  117. data/test/source/deal.with.dots.html +7 -0
  118. data/test/source/foo/_posts/bar/2008-12-12-topical-post.textile +8 -0
  119. data/test/source/index.html +22 -0
  120. data/test/source/sitemap.xml +32 -0
  121. data/test/source/symlink-test/symlinked-file +22 -0
  122. data/test/source/win/_posts/2009-05-24-yaml-linebreak.markdown +7 -0
  123. data/test/source/z_category/_posts/2008-9-23-categories.textile +6 -0
  124. data/test/suite.rb +11 -0
  125. data/test/test_command.rb +39 -0
  126. data/test/test_configuration.rb +137 -0
  127. data/test/test_convertible.rb +51 -0
  128. data/test/test_core_ext.rb +88 -0
  129. data/test/test_filters.rb +102 -0
  130. data/test/test_generated_site.rb +83 -0
  131. data/test/test_json_driver.rb +63 -0
  132. data/test/test_kramdown.rb +35 -0
  133. data/test/test_new_command.rb +104 -0
  134. data/test/test_page.rb +193 -0
  135. data/test/test_pager.rb +115 -0
  136. data/test/test_post.rb +573 -0
  137. data/test/test_rdiscount.rb +22 -0
  138. data/test/test_redcarpet.rb +61 -0
  139. data/test/test_redcloth.rb +86 -0
  140. data/test/test_site.rb +374 -0
  141. data/test/test_tags.rb +310 -0
  142. data/test/test_yaml_driver.rb +35 -0
  143. metadata +554 -0
@@ -0,0 +1,115 @@
1
+ require 'helper'
2
+
3
+ class TestPager < Test::Unit::TestCase
4
+
5
+ should "calculate number of pages" do
6
+ assert_equal(0, Pager.calculate_pages([], '2'))
7
+ assert_equal(1, Pager.calculate_pages([1], '2'))
8
+ assert_equal(1, Pager.calculate_pages([1,2], '2'))
9
+ assert_equal(2, Pager.calculate_pages([1,2,3], '2'))
10
+ assert_equal(2, Pager.calculate_pages([1,2,3,4], '2'))
11
+ assert_equal(3, Pager.calculate_pages([1,2,3,4,5], '2'))
12
+ end
13
+
14
+ context "pagination disabled" do
15
+ setup do
16
+ stub(Monad).configuration do
17
+ Monad::Configuration::DEFAULTS.merge({
18
+ 'source' => source_dir,
19
+ 'destination' => dest_dir
20
+ })
21
+ end
22
+ @config = Monad.configuration
23
+ end
24
+
25
+ should "report that pagination is disabled" do
26
+ page = OpenStruct.new({ :name => 'index.html', :dir => '/' })
27
+ assert !Pager.pagination_enabled?(@config, page)
28
+ end
29
+
30
+ end
31
+
32
+ context "pagination enabled for 2" do
33
+ setup do
34
+ stub(Monad).configuration do
35
+ Monad::Configuration::DEFAULTS.merge({
36
+ 'source' => source_dir,
37
+ 'destination' => dest_dir,
38
+ 'paginate' => 2
39
+ })
40
+ end
41
+
42
+ @config = Monad.configuration
43
+ @site = Site.new(@config)
44
+ @site.process
45
+ @posts = @site.posts
46
+ end
47
+
48
+ should "report that pagination is enabled" do
49
+ page = OpenStruct.new({ :name => 'index.html', :dir => '/' })
50
+ assert Pager.pagination_enabled?(@config, page)
51
+ end
52
+
53
+ context "with 4 posts" do
54
+ setup do
55
+ @posts = @site.posts[1..4] # limit to 4
56
+ end
57
+
58
+ should "create first pager" do
59
+ pager = Pager.new(@config, 1, @posts)
60
+ assert_equal(2, pager.posts.size)
61
+ assert_equal(2, pager.total_pages)
62
+ assert_nil(pager.previous_page)
63
+ assert_equal(2, pager.next_page)
64
+ end
65
+
66
+ should "create second pager" do
67
+ pager = Pager.new(@config, 2, @posts)
68
+ assert_equal(2, pager.posts.size)
69
+ assert_equal(2, pager.total_pages)
70
+ assert_equal(1, pager.previous_page)
71
+ assert_nil(pager.next_page)
72
+ end
73
+
74
+ should "not create third pager" do
75
+ assert_raise(RuntimeError) { Pager.new(@config, 3, @posts) }
76
+ end
77
+
78
+ end
79
+
80
+ context "with 5 posts" do
81
+ setup do
82
+ @posts = @site.posts[1..5] # limit to 5
83
+ end
84
+
85
+ should "create first pager" do
86
+ pager = Pager.new(@config, 1, @posts)
87
+ assert_equal(2, pager.posts.size)
88
+ assert_equal(3, pager.total_pages)
89
+ assert_nil(pager.previous_page)
90
+ assert_equal(2, pager.next_page)
91
+ end
92
+
93
+ should "create second pager" do
94
+ pager = Pager.new(@config, 2, @posts)
95
+ assert_equal(2, pager.posts.size)
96
+ assert_equal(3, pager.total_pages)
97
+ assert_equal(1, pager.previous_page)
98
+ assert_equal(3, pager.next_page)
99
+ end
100
+
101
+ should "create third pager" do
102
+ pager = Pager.new(@config, 3, @posts)
103
+ assert_equal(1, pager.posts.size)
104
+ assert_equal(3, pager.total_pages)
105
+ assert_equal(2, pager.previous_page)
106
+ assert_nil(pager.next_page)
107
+ end
108
+
109
+ should "not create fourth pager" do
110
+ assert_raise(RuntimeError) { Pager.new(@config, 4, @posts) }
111
+ end
112
+
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,573 @@
1
+ require 'helper'
2
+
3
+ class TestPost < Test::Unit::TestCase
4
+ def setup_post(file)
5
+ Post.new(@site, source_dir, '', file)
6
+ end
7
+
8
+ def do_render(post)
9
+ layouts = { "default" => Layout.new(@site, source_dir('_layouts'), "simple.html")}
10
+ post.render(layouts, {"site" => {"posts" => []}})
11
+ end
12
+
13
+ context "A Post" do
14
+ setup do
15
+ clear_dest
16
+ stub(Monad).configuration { Monad::Configuration::DEFAULTS }
17
+ @site = Site.new(Monad.configuration)
18
+ end
19
+
20
+ should "ensure valid posts are valid" do
21
+ assert Post.valid?("2008-09-09-foo-bar.textile")
22
+ assert Post.valid?("foo/bar/2008-09-09-foo-bar.textile")
23
+
24
+ assert !Post.valid?("lol2008-09-09-foo-bar.textile")
25
+ assert !Post.valid?("blah")
26
+ end
27
+
28
+ context "processing posts" do
29
+ setup do
30
+ @post = Post.allocate
31
+ @post.site = @site
32
+
33
+ @real_file = "2008-10-18-foo-bar.textile"
34
+ @fake_file = "2008-09-09-foo-bar.textile"
35
+ @source = source_dir('_posts')
36
+ end
37
+
38
+ should "keep date, title, and markup type" do
39
+ @post.categories = []
40
+ @post.process(@fake_file)
41
+
42
+ assert_equal Time.parse("2008-09-09"), @post.date
43
+ assert_equal "foo-bar", @post.slug
44
+ assert_equal ".textile", @post.ext
45
+ assert_equal "/2008/09/09", @post.dir
46
+ assert_equal "/2008/09/09/foo-bar", @post.id
47
+ end
48
+
49
+ should "create url based on date and title" do
50
+ @post.categories = []
51
+ @post.process(@fake_file)
52
+ assert_equal "/2008/09/09/foo-bar.html", @post.url
53
+ end
54
+
55
+ should "raise a good error on invalid post date" do
56
+ assert_raise Monad::FatalException do
57
+ @post.process("2009-27-03-foo-bar.textile")
58
+ end
59
+ end
60
+
61
+ should "CGI escape urls" do
62
+ @post.categories = []
63
+ @post.process("2009-03-12-hash-#1.markdown")
64
+ assert_equal "/2009/03/12/hash-%231.html", @post.url
65
+ assert_equal "/2009/03/12/hash-#1", @post.id
66
+ end
67
+
68
+ should "respect permalink in yaml front matter" do
69
+ file = "2008-12-03-permalinked-post.textile"
70
+ @post.process(file)
71
+ @post.read_yaml(@source, file)
72
+
73
+ assert_equal "my_category/permalinked-post", @post.permalink
74
+ assert_equal "/my_category", @post.dir
75
+ assert_equal "/my_category/permalinked-post", @post.url
76
+ end
77
+
78
+ context "with CRLF linebreaks" do
79
+ setup do
80
+ @real_file = "2009-05-24-yaml-linebreak.markdown"
81
+ @source = source_dir('win/_posts')
82
+ end
83
+ should "read yaml front-matter" do
84
+ @post.read_yaml(@source, @real_file)
85
+
86
+ assert_equal({"title" => "Test title", "layout" => "post", "tag" => "Ruby"}, @post.data)
87
+ assert_equal "This is the content", @post.content
88
+ end
89
+ end
90
+
91
+ context "with embedded triple dash" do
92
+ setup do
93
+ @real_file = "2010-01-08-triple-dash.markdown"
94
+ end
95
+ should "consume the embedded dashes" do
96
+ @post.read_yaml(@source, @real_file)
97
+
98
+ assert_equal({"title" => "Foo --- Bar"}, @post.data)
99
+ assert_equal "Triple the fun!", @post.content
100
+ end
101
+ end
102
+
103
+ context "with site wide permalink" do
104
+ setup do
105
+ @post.categories = []
106
+ end
107
+
108
+ context "with unspecified (date) style" do
109
+ setup do
110
+ @post.process(@fake_file)
111
+ end
112
+
113
+ should "process the url correctly" do
114
+ assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
115
+ assert_equal "/2008/09/09/foo-bar.html", @post.url
116
+ end
117
+ end
118
+
119
+ context "with unspecified (date) style and a category" do
120
+ setup do
121
+ @post.categories << "beer"
122
+ @post.process(@fake_file)
123
+ end
124
+
125
+ should "process the url correctly" do
126
+ assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
127
+ assert_equal "/beer/2008/09/09/foo-bar.html", @post.url
128
+ end
129
+ end
130
+
131
+ context "with unspecified (date) style and a numeric category" do
132
+ setup do
133
+ @post.categories << 2013
134
+ @post.process(@fake_file)
135
+ end
136
+
137
+ should "process the url correctly" do
138
+ assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
139
+ assert_equal "/2013/2008/09/09/foo-bar.html", @post.url
140
+ end
141
+ end
142
+
143
+ context "with specified layout of nil" do
144
+ setup do
145
+ file = '2013-01-12-nil-layout.textile'
146
+ @post = setup_post(file)
147
+ @post.process(file)
148
+ end
149
+
150
+ should "layout of nil is respected" do
151
+ assert_equal "nil", @post.data["layout"]
152
+ end
153
+ end
154
+
155
+ context "with unspecified (date) style and categories" do
156
+ setup do
157
+ @post.categories << "food"
158
+ @post.categories << "beer"
159
+ @post.process(@fake_file)
160
+ end
161
+
162
+ should "process the url correctly" do
163
+ assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
164
+ assert_equal "/food/beer/2008/09/09/foo-bar.html", @post.url
165
+ end
166
+ end
167
+
168
+ context "with space (categories)" do
169
+ setup do
170
+ @post.categories << "French cuisine"
171
+ @post.categories << "Belgian beer"
172
+ @post.process(@fake_file)
173
+ end
174
+
175
+ should "process the url correctly" do
176
+ assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
177
+ assert_equal "/French%20cuisine/Belgian%20beer/2008/09/09/foo-bar.html", @post.url
178
+ end
179
+ end
180
+
181
+ context "with none style" do
182
+ setup do
183
+ @post.site.permalink_style = :none
184
+ @post.process(@fake_file)
185
+ end
186
+
187
+ should "process the url correctly" do
188
+ assert_equal "/:categories/:title.html", @post.template
189
+ assert_equal "/foo-bar.html", @post.url
190
+ end
191
+ end
192
+
193
+ context "with pretty style" do
194
+ setup do
195
+ @post.site.permalink_style = :pretty
196
+ @post.process(@fake_file)
197
+ end
198
+
199
+ should "process the url correctly" do
200
+ assert_equal "/:categories/:year/:month/:day/:title/", @post.template
201
+ assert_equal "/2008/09/09/foo-bar/", @post.url
202
+ end
203
+ end
204
+
205
+ context "with ordinal style" do
206
+ setup do
207
+ @post.site.permalink_style = :ordinal
208
+ @post.process(@fake_file)
209
+ end
210
+
211
+ should "process the url correctly" do
212
+ assert_equal "/:categories/:year/:y_day/:title.html", @post.template
213
+ assert_equal "/2008/253/foo-bar.html", @post.url
214
+ end
215
+ end
216
+
217
+ context "with custom date permalink" do
218
+ setup do
219
+ @post.site.permalink_style = '/:categories/:year/:i_month/:i_day/:title/'
220
+ @post.process(@fake_file)
221
+ end
222
+
223
+ should "process the url correctly" do
224
+ assert_equal "/2008/9/9/foo-bar/", @post.url
225
+ end
226
+ end
227
+
228
+ context "with custom abbreviated month date permalink" do
229
+ setup do
230
+ @post.site.permalink_style = '/:categories/:year/:short_month/:day/:title/'
231
+ @post.process(@fake_file)
232
+ end
233
+
234
+ should "process the url correctly" do
235
+ assert_equal "/2008/Sep/09/foo-bar/", @post.url
236
+ end
237
+ end
238
+
239
+ context "with prefix style and no extension" do
240
+ setup do
241
+ @post.site.permalink_style = "/prefix/:title"
242
+ @post.process(@fake_file)
243
+ end
244
+
245
+ should "process the url correctly" do
246
+ assert_equal "/prefix/:title", @post.template
247
+ assert_equal "/prefix/foo-bar", @post.url
248
+ end
249
+ end
250
+ end
251
+
252
+ should "read yaml front-matter" do
253
+ @post.read_yaml(@source, @real_file)
254
+
255
+ assert_equal({"title" => "Foo Bar", "layout" => "default"}, @post.data)
256
+ assert_equal "h1. {{ page.title }}\n\nBest *post* ever", @post.content
257
+ end
258
+
259
+ should "transform textile" do
260
+ @post.process(@real_file)
261
+ @post.read_yaml(@source, @real_file)
262
+ @post.transform
263
+
264
+ assert_equal "<h1>{{ page.title }}</h1>\n<p>Best <strong>post</strong> ever</p>", @post.content
265
+ end
266
+
267
+ context "#excerpt" do
268
+ setup do
269
+ file = "2013-01-02-post-excerpt.markdown"
270
+ @post.process(file)
271
+ @post.read_yaml(@source, file)
272
+ @post.transform
273
+ end
274
+
275
+ should "return first paragraph by default" do
276
+ assert @post.excerpt.include?("First paragraph"), "contains first paragraph"
277
+ assert !@post.excerpt.include?("Second paragraph"), "does not contains second paragraph"
278
+ assert !@post.excerpt.include?("Third paragraph"), "does not contains third paragraph"
279
+ end
280
+
281
+ should "correctly resolve link references" do
282
+ assert @post.excerpt.include?("www.monadrb.com"), "contains referenced link URL"
283
+ end
284
+
285
+ should "return rendered HTML" do
286
+ assert_equal "<p>First paragraph with <a href='http://www.monadrb.com/'>link ref</a>.</p>",
287
+ @post.excerpt
288
+ end
289
+
290
+ context "with excerpt_separator setting" do
291
+ setup do
292
+ file = "2013-01-02-post-excerpt.markdown"
293
+
294
+ @post.site.config['excerpt_separator'] = "\n---\n"
295
+
296
+ @post.process(file)
297
+ @post.read_yaml(@source, file)
298
+ @post.transform
299
+ end
300
+
301
+ should "respect given separator" do
302
+ assert @post.excerpt.include?("First paragraph"), "contains first paragraph"
303
+ assert @post.excerpt.include?("Second paragraph"), "contains second paragraph"
304
+ assert !@post.excerpt.include?("Third paragraph"), "does not contains third paragraph"
305
+ end
306
+
307
+ should "replace separator with new-lines" do
308
+ assert !@post.excerpt.include?("---"), "does not contains separator"
309
+ end
310
+ end
311
+
312
+ context "with custom excerpt" do
313
+ setup do
314
+ file = "2013-04-11-custom-excerpt.markdown"
315
+ @post = setup_post(file)
316
+ do_render(@post)
317
+ end
318
+
319
+ should "use custom excerpt" do
320
+ assert_equal("I can set a custom excerpt", @post.excerpt)
321
+ end
322
+
323
+ should "expose custom excerpt to liquid" do
324
+ assert @post.content.include?("I can use the excerpt: <quote>I can set a custom excerpt</quote>"), "Exposes incorrect excerpt to liquid."
325
+ end
326
+
327
+ end
328
+
329
+ end
330
+ end
331
+
332
+ context "when in a site" do
333
+ setup do
334
+ clear_dest
335
+ stub(Monad).configuration { Monad::Configuration::DEFAULTS }
336
+ @site = Site.new(Monad.configuration)
337
+ @site.posts = [setup_post('2008-02-02-published.textile'),
338
+ setup_post('2009-01-27-categories.textile')]
339
+ end
340
+
341
+ should "have next post" do
342
+ assert_equal(@site.posts.last, @site.posts.first.next)
343
+ end
344
+
345
+ should "have previous post" do
346
+ assert_equal(@site.posts.first, @site.posts.last.previous)
347
+ end
348
+
349
+ should "not have previous post if first" do
350
+ assert_equal(nil, @site.posts.first.previous)
351
+ end
352
+
353
+ should "not have next post if last" do
354
+ assert_equal(nil, @site.posts.last.next)
355
+ end
356
+ end
357
+
358
+ context "initializing posts" do
359
+ should "publish when published yaml is no specified" do
360
+ post = setup_post("2008-02-02-published.textile")
361
+ assert_equal true, post.published
362
+ end
363
+
364
+ should "not published when published yaml is false" do
365
+ post = setup_post("2008-02-02-not-published.textile")
366
+ assert_equal false, post.published
367
+ end
368
+
369
+ should "recognize date in yaml" do
370
+ post = setup_post("2010-01-09-date-override.textile")
371
+ do_render(post)
372
+ assert_equal Time, post.date.class
373
+ assert_equal Time, post.to_liquid["date"].class
374
+ assert_equal "/2010/01/10/date-override.html", post.url
375
+ assert_equal "<p>Post with a front matter date</p>\n<p>10 Jan 2010</p>", post.output
376
+ end
377
+
378
+ should "recognize time in yaml" do
379
+ post = setup_post("2010-01-09-time-override.textile")
380
+ do_render(post)
381
+ assert_equal Time, post.date.class
382
+ assert_equal Time, post.to_liquid["date"].class
383
+ assert_equal "/2010/01/10/time-override.html", post.url
384
+ assert_equal "<p>Post with a front matter time</p>\n<p>10 Jan 2010</p>", post.output
385
+ end
386
+
387
+ should "recognize time with timezone in yaml" do
388
+ post = setup_post("2010-01-09-timezone-override.textile")
389
+ do_render(post)
390
+ assert_equal Time, post.date.class
391
+ assert_equal Time, post.to_liquid["date"].class
392
+ assert_equal "/2010/01/10/timezone-override.html", post.url
393
+ assert_equal "<p>Post with a front matter time with timezone</p>\n<p>10 Jan 2010</p>", post.output
394
+ end
395
+
396
+ should "to_liquid prioritizes post attributes over data" do
397
+ post = setup_post("2010-01-16-override-data.textile")
398
+ assert_equal Array, post.tags.class
399
+ assert_equal Array, post.to_liquid["tags"].class
400
+ assert_equal Time, post.date.class
401
+ assert_equal Time, post.to_liquid["date"].class
402
+ end
403
+
404
+ should "recognize category in yaml" do
405
+ post = setup_post("2009-01-27-category.textile")
406
+ assert post.categories.include?('foo')
407
+ end
408
+
409
+ should "recognize several categories in yaml" do
410
+ post = setup_post("2009-01-27-categories.textile")
411
+ assert post.categories.include?('foo')
412
+ assert post.categories.include?('bar')
413
+ assert post.categories.include?('baz')
414
+ end
415
+
416
+ should "recognize empty category in yaml" do
417
+ post = setup_post("2009-01-27-empty-category.textile")
418
+ assert_equal [], post.categories
419
+ end
420
+
421
+ should "recognize empty categories in yaml" do
422
+ post = setup_post("2009-01-27-empty-categories.textile")
423
+ assert_equal [], post.categories
424
+ end
425
+
426
+ should "recognize number category in yaml" do
427
+ post = setup_post("2013-05-10-number-category.textile")
428
+ assert post.categories.include?('2013')
429
+ assert !post.categories.include?(2013)
430
+ end
431
+
432
+ should "recognize tag in yaml" do
433
+ post = setup_post("2009-05-18-tag.textile")
434
+ assert post.tags.include?('code')
435
+ end
436
+
437
+ should "recognize tags in yaml" do
438
+ post = setup_post("2009-05-18-tags.textile")
439
+ assert post.tags.include?('food')
440
+ assert post.tags.include?('cooking')
441
+ assert post.tags.include?('pizza')
442
+ end
443
+
444
+ should "recognize empty tag in yaml" do
445
+ post = setup_post("2009-05-18-empty-tag.textile")
446
+ assert_equal [], post.tags
447
+ end
448
+
449
+ should "recognize empty tags in yaml" do
450
+ post = setup_post("2009-05-18-empty-tags.textile")
451
+ assert_equal [], post.tags
452
+ end
453
+
454
+ should "allow no yaml" do
455
+ post = setup_post("2009-06-22-no-yaml.textile")
456
+ assert_equal "No YAML.", post.content
457
+ end
458
+
459
+ should "allow empty yaml" do
460
+ post = setup_post("2009-06-22-empty-yaml.textile")
461
+ assert_equal "Empty YAML.", post.content
462
+ end
463
+
464
+ context "rendering" do
465
+ setup do
466
+ clear_dest
467
+ end
468
+
469
+ should "render properly" do
470
+ post = setup_post("2008-10-18-foo-bar.textile")
471
+ do_render(post)
472
+ assert_equal "<<< <h1>Foo Bar</h1>\n<p>Best <strong>post</strong> ever</p> >>>", post.output
473
+ end
474
+
475
+ should "write properly" do
476
+ post = setup_post("2008-10-18-foo-bar.textile")
477
+ do_render(post)
478
+ post.write(dest_dir)
479
+
480
+ assert File.directory?(dest_dir)
481
+ assert File.exists?(File.join(dest_dir, '2008', '10', '18', 'foo-bar.html'))
482
+ end
483
+
484
+ should "write properly without html extension" do
485
+ post = setup_post("2008-10-18-foo-bar.textile")
486
+ post.site.permalink_style = ":title"
487
+ do_render(post)
488
+ post.write(dest_dir)
489
+
490
+ assert File.directory?(dest_dir)
491
+ assert File.exists?(File.join(dest_dir, 'foo-bar', 'index.html'))
492
+ end
493
+
494
+ should "insert data" do
495
+ post = setup_post("2008-11-21-complex.textile")
496
+ do_render(post)
497
+
498
+ assert_equal "<<< <p>url: /2008/11/21/complex.html<br />\ndate: #{Time.parse("2008-11-21")}<br />\nid: /2008/11/21/complex</p> >>>", post.output
499
+ end
500
+
501
+ should "include templates" do
502
+ post = setup_post("2008-12-13-include.markdown")
503
+ post.site.source = File.join(File.dirname(__FILE__), 'source')
504
+ do_render(post)
505
+
506
+ assert_equal "<<< <hr />\n<p>Tom Preston-Werner github.com/mojombo</p>\n\n<p>This <em>is</em> cool</p> >>>", post.output
507
+ end
508
+
509
+ should "render date specified in front matter properly" do
510
+ post = setup_post("2010-01-09-date-override.textile")
511
+ do_render(post)
512
+
513
+ assert_equal "<p>Post with a front matter date</p>\n<p>10 Jan 2010</p>", post.output
514
+ end
515
+
516
+ should "render time specified in front matter properly" do
517
+ post = setup_post("2010-01-09-time-override.textile")
518
+ do_render(post)
519
+
520
+ assert_equal "<p>Post with a front matter time</p>\n<p>10 Jan 2010</p>", post.output
521
+ end
522
+
523
+ end
524
+ end
525
+
526
+ should "generate categories and topics" do
527
+ post = Post.new(@site, File.join(File.dirname(__FILE__), *%w[source]), 'foo', 'bar/2008-12-12-topical-post.textile')
528
+ assert_equal ['foo'], post.categories
529
+ end
530
+ end
531
+
532
+ context "converter file extension settings" do
533
+ setup do
534
+ stub(Monad).configuration { Monad::Configuration::DEFAULTS }
535
+ @site = Site.new(Monad.configuration)
536
+ end
537
+
538
+ should "process .md as markdown under default configuration" do
539
+ post = setup_post '2011-04-12-md-extension.md'
540
+ conv = post.converter
541
+ assert conv.kind_of? Monad::Converters::Markdown
542
+ end
543
+
544
+ should "process .text as identity under default configuration" do
545
+ post = setup_post '2011-04-12-text-extension.text'
546
+ conv = post.converter
547
+ assert conv.kind_of? Monad::Converters::Identity
548
+ end
549
+
550
+ should "process .text as markdown under alternate configuration" do
551
+ @site.config['markdown_ext'] = 'markdown,mdw,mdwn,md,text'
552
+ post = setup_post '2011-04-12-text-extension.text'
553
+ conv = post.converter
554
+ assert conv.kind_of? Monad::Converters::Markdown
555
+ end
556
+
557
+ should "process .md as markdown under alternate configuration" do
558
+ @site.config['markdown_ext'] = 'markdown,mkd,mkdn,md,text'
559
+ post = setup_post '2011-04-12-text-extension.text'
560
+ conv = post.converter
561
+ assert conv.kind_of? Monad::Converters::Markdown
562
+ end
563
+
564
+ should "process .text as textile under alternate configuration" do
565
+ @site.config['textile_ext'] = 'textile,text'
566
+ post = setup_post '2011-04-12-text-extension.text'
567
+ conv = post.converter
568
+ assert conv.kind_of? Monad::Converters::Textile
569
+ end
570
+
571
+ end
572
+
573
+ end