jekyll-reloaded 0.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/Gemfile +2 -0
  2. data/History.txt +321 -0
  3. data/LICENSE +21 -0
  4. data/README.textile +41 -0
  5. data/Rakefile +161 -0
  6. data/bin/jekyll +289 -0
  7. data/cucumber.yml +1 -0
  8. data/features/create_sites.feature +112 -0
  9. data/features/embed_filters.feature +60 -0
  10. data/features/markdown.feature +30 -0
  11. data/features/pagination.feature +27 -0
  12. data/features/permalinks.feature +65 -0
  13. data/features/post_data.feature +153 -0
  14. data/features/site_configuration.feature +145 -0
  15. data/features/site_data.feature +82 -0
  16. data/features/step_definitions/jekyll_steps.rb +145 -0
  17. data/features/support/env.rb +19 -0
  18. data/jekyll.gemspec +146 -0
  19. data/lib/guard/jekyll.rb +57 -0
  20. data/lib/jekyll/converter.rb +50 -0
  21. data/lib/jekyll/converters/identity.rb +22 -0
  22. data/lib/jekyll/converters/markdown.rb +125 -0
  23. data/lib/jekyll/converters/textile.rb +50 -0
  24. data/lib/jekyll/convertible.rb +116 -0
  25. data/lib/jekyll/core_ext.rb +52 -0
  26. data/lib/jekyll/errors.rb +6 -0
  27. data/lib/jekyll/filters.rb +118 -0
  28. data/lib/jekyll/generator.rb +7 -0
  29. data/lib/jekyll/generators/pagination.rb +113 -0
  30. data/lib/jekyll/layout.rb +51 -0
  31. data/lib/jekyll/live_site.rb +216 -0
  32. data/lib/jekyll/migrators/csv.rb +26 -0
  33. data/lib/jekyll/migrators/drupal.rb +103 -0
  34. data/lib/jekyll/migrators/enki.rb +49 -0
  35. data/lib/jekyll/migrators/joomla.rb +53 -0
  36. data/lib/jekyll/migrators/marley.rb +52 -0
  37. data/lib/jekyll/migrators/mephisto.rb +84 -0
  38. data/lib/jekyll/migrators/mt.rb +86 -0
  39. data/lib/jekyll/migrators/posterous.rb +67 -0
  40. data/lib/jekyll/migrators/rss.rb +47 -0
  41. data/lib/jekyll/migrators/textpattern.rb +58 -0
  42. data/lib/jekyll/migrators/tumblr.rb +195 -0
  43. data/lib/jekyll/migrators/typo.rb +51 -0
  44. data/lib/jekyll/migrators/wordpress.rb +294 -0
  45. data/lib/jekyll/migrators/wordpressdotcom.rb +70 -0
  46. data/lib/jekyll/page.rb +160 -0
  47. data/lib/jekyll/plugin.rb +77 -0
  48. data/lib/jekyll/post.rb +262 -0
  49. data/lib/jekyll/site.rb +339 -0
  50. data/lib/jekyll/static_file.rb +77 -0
  51. data/lib/jekyll/tags/highlight.rb +118 -0
  52. data/lib/jekyll/tags/include.rb +37 -0
  53. data/lib/jekyll/tags/post_url.rb +38 -0
  54. data/lib/jekyll.rb +134 -0
  55. data/test/helper.rb +34 -0
  56. data/test/source/.htaccess +8 -0
  57. data/test/source/_includes/sig.markdown +3 -0
  58. data/test/source/_layouts/default.html +27 -0
  59. data/test/source/_layouts/simple.html +1 -0
  60. data/test/source/_posts/2008-02-02-not-published.textile +8 -0
  61. data/test/source/_posts/2008-02-02-published.textile +8 -0
  62. data/test/source/_posts/2008-10-18-foo-bar.textile +8 -0
  63. data/test/source/_posts/2008-11-21-complex.textile +8 -0
  64. data/test/source/_posts/2008-12-03-permalinked-post.textile +9 -0
  65. data/test/source/_posts/2008-12-13-include.markdown +8 -0
  66. data/test/source/_posts/2009-01-27-array-categories.textile +10 -0
  67. data/test/source/_posts/2009-01-27-categories.textile +7 -0
  68. data/test/source/_posts/2009-01-27-category.textile +7 -0
  69. data/test/source/_posts/2009-01-27-empty-categories.textile +7 -0
  70. data/test/source/_posts/2009-01-27-empty-category.textile +7 -0
  71. data/test/source/_posts/2009-03-12-hash-#1.markdown +6 -0
  72. data/test/source/_posts/2009-05-18-empty-tag.textile +6 -0
  73. data/test/source/_posts/2009-05-18-empty-tags.textile +6 -0
  74. data/test/source/_posts/2009-05-18-tag.textile +6 -0
  75. data/test/source/_posts/2009-05-18-tags.textile +9 -0
  76. data/test/source/_posts/2009-06-22-empty-yaml.textile +3 -0
  77. data/test/source/_posts/2009-06-22-no-yaml.textile +1 -0
  78. data/test/source/_posts/2010-01-08-triple-dash.markdown +5 -0
  79. data/test/source/_posts/2010-01-09-date-override.textile +7 -0
  80. data/test/source/_posts/2010-01-09-time-override.textile +7 -0
  81. data/test/source/_posts/2010-01-09-timezone-override.textile +7 -0
  82. data/test/source/_posts/2010-01-16-override-data.textile +4 -0
  83. data/test/source/_posts/2011-04-12-md-extension.md +7 -0
  84. data/test/source/_posts/2011-04-12-text-extension.text +0 -0
  85. data/test/source/about.html +6 -0
  86. data/test/source/category/_posts/2008-9-23-categories.textile +6 -0
  87. data/test/source/contacts.html +5 -0
  88. data/test/source/css/screen.css +76 -0
  89. data/test/source/deal.with.dots.html +7 -0
  90. data/test/source/foo/_posts/bar/2008-12-12-topical-post.textile +8 -0
  91. data/test/source/index.html +22 -0
  92. data/test/source/sitemap.xml +32 -0
  93. data/test/source/win/_posts/2009-05-24-yaml-linebreak.markdown +7 -0
  94. data/test/source/z_category/_posts/2008-9-23-categories.textile +6 -0
  95. data/test/suite.rb +11 -0
  96. data/test/test_configuration.rb +29 -0
  97. data/test/test_core_ext.rb +66 -0
  98. data/test/test_filters.rb +62 -0
  99. data/test/test_generated_site.rb +72 -0
  100. data/test/test_kramdown.rb +23 -0
  101. data/test/test_page.rb +117 -0
  102. data/test/test_pager.rb +113 -0
  103. data/test/test_post.rb +450 -0
  104. data/test/test_rdiscount.rb +18 -0
  105. data/test/test_redcarpet.rb +21 -0
  106. data/test/test_redcloth.rb +86 -0
  107. data/test/test_site.rb +220 -0
  108. data/test/test_tags.rb +201 -0
  109. metadata +332 -0
data/test/test_site.rb ADDED
@@ -0,0 +1,220 @@
1
+ require 'helper'
2
+
3
+ class TestSite < Test::Unit::TestCase
4
+ context "configuring sites" do
5
+ should "have an array for plugins by default" do
6
+ site = Site.new(Jekyll::DEFAULTS)
7
+ assert_equal [File.join(Dir.pwd, '_plugins')], site.plugins
8
+ end
9
+
10
+ should "have an array for plugins if passed as a string" do
11
+ site = Site.new(Jekyll::DEFAULTS.merge({'plugins' => '/tmp/plugins'}))
12
+ assert_equal ['/tmp/plugins'], site.plugins
13
+ end
14
+
15
+ should "have an array for plugins if passed as an array" do
16
+ site = Site.new(Jekyll::DEFAULTS.merge({'plugins' => ['/tmp/plugins', '/tmp/otherplugins']}))
17
+ assert_equal ['/tmp/plugins', '/tmp/otherplugins'], site.plugins
18
+ end
19
+
20
+ should "have an empty array for plugins if nothing is passed" do
21
+ site = Site.new(Jekyll::DEFAULTS.merge({'plugins' => []}))
22
+ assert_equal [], site.plugins
23
+ end
24
+
25
+ should "have an empty array for plugins if nil is passed" do
26
+ site = Site.new(Jekyll::DEFAULTS.merge({'plugins' => nil}))
27
+ assert_equal [], site.plugins
28
+ end
29
+ end
30
+ context "creating sites" do
31
+ setup do
32
+ stub(Jekyll).configuration do
33
+ Jekyll::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir})
34
+ end
35
+ @site = Site.new(Jekyll.configuration)
36
+ end
37
+
38
+ should "have an empty tag hash by default" do
39
+ assert_equal Hash.new, @site.tags
40
+ end
41
+
42
+ should "reset data before processing" do
43
+ clear_dest
44
+ @site.process
45
+ before_posts = @site.posts.length
46
+ before_layouts = @site.layouts.length
47
+ before_categories = @site.categories.length
48
+ before_tags = @site.tags.length
49
+ before_pages = @site.pages.length
50
+ before_static_files = @site.static_files.length
51
+ before_time = @site.time
52
+
53
+ @site.process
54
+ assert_equal before_posts, @site.posts.length
55
+ assert_equal before_layouts, @site.layouts.length
56
+ assert_equal before_categories, @site.categories.length
57
+ assert_equal before_tags, @site.tags.length
58
+ assert_equal before_pages, @site.pages.length
59
+ assert_equal before_static_files, @site.static_files.length
60
+ assert before_time <= @site.time
61
+ end
62
+
63
+ should "write only modified static files" do
64
+ clear_dest
65
+ StaticFile.reset_cache
66
+
67
+ @site.process
68
+ some_static_file = @site.static_files[0].path
69
+ dest = File.expand_path(@site.static_files[0].destination(@site.dest))
70
+ mtime1 = File.stat(dest).mtime.to_i # first run must generate dest file
71
+
72
+ # need to sleep because filesystem timestamps have best resolution in seconds
73
+ sleep 1
74
+ @site.process
75
+ mtime2 = File.stat(dest).mtime.to_i
76
+ assert_equal mtime1, mtime2
77
+
78
+ # simulate file modification by user
79
+ FileUtils.touch some_static_file
80
+
81
+ sleep 1
82
+ @site.process
83
+ mtime3 = File.stat(dest).mtime.to_i
84
+ assert_not_equal mtime2, mtime3 # must be regenerated!
85
+
86
+ sleep 1
87
+ @site.process
88
+ mtime4 = File.stat(dest).mtime.to_i
89
+ assert_equal mtime3, mtime4 # no modifications, so must be the same
90
+ end
91
+
92
+ should "write static files if not modified but missing in destination" do
93
+ clear_dest
94
+ StaticFile.reset_cache
95
+
96
+ @site.process
97
+ some_static_file = @site.static_files[0].path
98
+ dest = File.expand_path(@site.static_files[0].destination(@site.dest))
99
+ mtime1 = File.stat(dest).mtime.to_i # first run must generate dest file
100
+
101
+ # need to sleep because filesystem timestamps have best resolution in seconds
102
+ sleep 1
103
+ @site.process
104
+ mtime2 = File.stat(dest).mtime.to_i
105
+ assert_equal mtime1, mtime2
106
+
107
+ # simulate destination file deletion
108
+ File.unlink dest
109
+
110
+ sleep 1
111
+ @site.process
112
+ mtime3 = File.stat(dest).mtime.to_i
113
+ assert_not_equal mtime2, mtime3 # must be regenerated and differ!
114
+
115
+ sleep 1
116
+ @site.process
117
+ mtime4 = File.stat(dest).mtime.to_i
118
+ assert_equal mtime3, mtime4 # no modifications, so must be the same
119
+ end
120
+
121
+ should "read layouts" do
122
+ @site.read_layouts
123
+ assert_equal ["default", "simple"].sort, @site.layouts.keys.sort
124
+ end
125
+
126
+ should "read posts" do
127
+ @site.read_posts('')
128
+ posts = Dir[source_dir('_posts', '*')]
129
+ assert_equal posts.size - 1, @site.posts.size
130
+ end
131
+
132
+ should "deploy payload" do
133
+ clear_dest
134
+ @site.process
135
+
136
+ posts = Dir[source_dir("**", "_posts", "*")]
137
+ categories = %w(bar baz category foo z_category publish_test win).sort
138
+
139
+ assert_equal posts.size - 1, @site.posts.size
140
+ assert_equal categories, @site.categories.keys.sort
141
+ assert_equal 4, @site.categories['foo'].size
142
+ end
143
+
144
+ should "filter entries" do
145
+ ent1 = %w[foo.markdown bar.markdown baz.markdown #baz.markdown#
146
+ .baz.markdow foo.markdown~]
147
+ ent2 = %w[.htaccess _posts _pages bla.bla]
148
+
149
+ assert_equal %w[foo.markdown bar.markdown baz.markdown], @site.filter_entries(ent1)
150
+ assert_equal %w[.htaccess bla.bla], @site.filter_entries(ent2)
151
+ end
152
+
153
+ should "filter entries with exclude" do
154
+ excludes = %w[README TODO]
155
+ files = %w[index.html site.css .htaccess]
156
+
157
+ @site.exclude = excludes
158
+ assert_equal files, @site.filter_entries(excludes + files)
159
+ end
160
+
161
+ should "not filter entries within include" do
162
+ includes = %w[_index.html .htaccess]
163
+ files = %w[index.html _index.html .htaccess]
164
+
165
+ @site.include = includes
166
+ assert_equal files, @site.filter_entries(files)
167
+ end
168
+
169
+ context 'with orphaned files in destination' do
170
+ setup do
171
+ clear_dest
172
+ @site.process
173
+ # generate some orphaned files:
174
+ # hidden file
175
+ File.open(dest_dir('.htpasswd'), 'w')
176
+ # single file
177
+ File.open(dest_dir('obsolete.html'), 'w')
178
+ # single file in sub directory
179
+ FileUtils.mkdir(dest_dir('qux'))
180
+ File.open(dest_dir('qux/obsolete.html'), 'w')
181
+ # empty directory
182
+ FileUtils.mkdir(dest_dir('quux'))
183
+ end
184
+
185
+ teardown do
186
+ FileUtils.rm_f(dest_dir('.htpasswd'))
187
+ FileUtils.rm_f(dest_dir('obsolete.html'))
188
+ FileUtils.rm_rf(dest_dir('qux'))
189
+ FileUtils.rm_f(dest_dir('quux'))
190
+ end
191
+
192
+ should 'remove orphaned files in destination' do
193
+ @site.process
194
+ assert !File.exist?(dest_dir('.htpasswd'))
195
+ assert !File.exist?(dest_dir('obsolete.html'))
196
+ assert !File.exist?(dest_dir('qux'))
197
+ assert !File.exist?(dest_dir('quux'))
198
+ end
199
+
200
+ end
201
+
202
+ context 'with an invalid markdown processor in the configuration' do
203
+ should 'not throw an error at initialization time' do
204
+ bad_processor = 'not a processor name'
205
+ assert_nothing_raised do
206
+ Site.new(Jekyll.configuration.merge({ 'markdown' => bad_processor }))
207
+ end
208
+ end
209
+
210
+ should 'throw FatalException at process time' do
211
+ bad_processor = 'not a processor name'
212
+ s = Site.new(Jekyll.configuration.merge({ 'markdown' => bad_processor }))
213
+ assert_raise Jekyll::FatalException do
214
+ s.process
215
+ end
216
+ end
217
+ end
218
+
219
+ end
220
+ end
data/test/test_tags.rb ADDED
@@ -0,0 +1,201 @@
1
+ # coding: utf-8
2
+
3
+ require 'helper'
4
+
5
+ class TestTags < Test::Unit::TestCase
6
+
7
+ def create_post(content, override = {}, converter_class = Jekyll::MarkdownConverter)
8
+ stub(Jekyll).configuration do
9
+ Jekyll::DEFAULTS.merge({'pygments' => true}).merge(override)
10
+ end
11
+ site = Site.new(Jekyll.configuration)
12
+
13
+ if override['read_posts']
14
+ site.read_posts('')
15
+ end
16
+
17
+ info = { :filters => [Jekyll::Filters], :registers => { :site => site } }
18
+ @converter = site.converters.find { |c| c.class == converter_class }
19
+ payload = { "pygments_prefix" => @converter.pygments_prefix,
20
+ "pygments_suffix" => @converter.pygments_suffix }
21
+
22
+ @result = Liquid::Template.parse(content).render(payload, info)
23
+ @result = @converter.convert(@result)
24
+ end
25
+
26
+ def fill_post(code, override = {})
27
+ content = <<CONTENT
28
+ ---
29
+ title: This is a test
30
+ ---
31
+
32
+ This document results in a markdown error with maruku
33
+
34
+ {% highlight text %}#{code}{% endhighlight %}
35
+ CONTENT
36
+ create_post(content, override)
37
+ end
38
+
39
+ context "language name" do
40
+ should "match only the required set of chars" do
41
+ r = Jekyll::HighlightBlock::SYNTAX
42
+ assert_match r, "ruby"
43
+ assert_match r, "c#"
44
+ assert_match r, "xml+cheetah"
45
+ assert_match r, "x.y"
46
+ assert_match r, "coffee-script"
47
+
48
+ assert_no_match r, "blah^"
49
+
50
+ assert_match r, "ruby key=val"
51
+ assert_match r, "ruby a=b c=d"
52
+ end
53
+ end
54
+
55
+ context "initialized tag" do
56
+ should "work" do
57
+ tag = Jekyll::HighlightBlock.new('highlight', 'ruby ', ["test", "{% endhighlight %}", "\n"])
58
+ assert_equal({}, tag.instance_variable_get(:@options))
59
+
60
+ tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos ', ["test", "{% endhighlight %}", "\n"])
61
+ assert_equal({'O' => "linenos=inline"}, tag.instance_variable_get(:@options))
62
+
63
+ tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table ', ["test", "{% endhighlight %}", "\n"])
64
+ assert_equal({'O' => "linenos=table"}, tag.instance_variable_get(:@options))
65
+
66
+ tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table nowrap', ["test", "{% endhighlight %}", "\n"])
67
+ assert_equal({'O' => "linenos=table,nowrap=true"}, tag.instance_variable_get(:@options))
68
+
69
+ tag = Jekyll::HighlightBlock.new('highlight', 'ruby linenos=table cssclass=hl', ["test", "{% endhighlight %}", "\n"])
70
+ assert_equal({'O' => "cssclass=hl,linenos=table"}, tag.instance_variable_get(:@options))
71
+ end
72
+ end
73
+
74
+ context "post content has highlight tag" do
75
+ setup do
76
+ fill_post("test")
77
+ end
78
+
79
+ should "not cause a markdown error" do
80
+ assert_no_match /markdown\-html\-error/, @result
81
+ end
82
+
83
+ should "render markdown with pygments line handling" do
84
+ assert_match %{<pre><code class='text'>test\n</code></pre>}, @result
85
+ end
86
+ end
87
+
88
+ context "post content has highlight with file reference" do
89
+ setup do
90
+ fill_post("./jekyll.gemspec")
91
+ end
92
+
93
+ should "not embed the file" do
94
+ assert_match %{<pre><code class='text'>./jekyll.gemspec\n</code></pre>}, @result
95
+ end
96
+ end
97
+
98
+ context "post content has highlight tag with UTF character" do
99
+ setup do
100
+ fill_post("Æ")
101
+ end
102
+
103
+ should "render markdown with pygments line handling" do
104
+ assert_match %{<pre><code class='text'>Æ\n</code></pre>}, @result
105
+ end
106
+ end
107
+
108
+ context "simple post with markdown and pre tags" do
109
+ setup do
110
+ @content = <<CONTENT
111
+ ---
112
+ title: Maruku vs. RDiscount
113
+ ---
114
+
115
+ _FIGHT!_
116
+
117
+ {% highlight ruby %}
118
+ puts "3..2..1.."
119
+ {% endhighlight %}
120
+
121
+ *FINISH HIM*
122
+ CONTENT
123
+ end
124
+
125
+ context "using Textile" do
126
+ setup do
127
+ create_post(@content, {}, Jekyll::TextileConverter)
128
+ end
129
+
130
+ # Broken in RedCloth 4.1.9
131
+ should "not textilize highlight block" do
132
+ assert_no_match %r{3\.\.2\.\.1\.\.&quot;</span><br />}, @result
133
+ end
134
+ end
135
+
136
+ context "using Maruku" do
137
+ setup do
138
+ create_post(@content)
139
+ end
140
+
141
+ should "parse correctly" do
142
+ assert_match %r{<em>FIGHT!</em>}, @result
143
+ assert_match %r{<em>FINISH HIM</em>}, @result
144
+ end
145
+ end
146
+
147
+ context "using RDiscount" do
148
+ setup do
149
+ create_post(@content, 'markdown' => 'rdiscount')
150
+ end
151
+
152
+ should "parse correctly" do
153
+ assert_match %r{<em>FIGHT!</em>}, @result
154
+ assert_match %r{<em>FINISH HIM</em>}, @result
155
+ end
156
+ end
157
+
158
+ context "using Kramdown" do
159
+ setup do
160
+ create_post(@content, 'markdown' => 'kramdown')
161
+ end
162
+
163
+ should "parse correctly" do
164
+ assert_match %r{<em>FIGHT!</em>}, @result
165
+ assert_match %r{<em>FINISH HIM</em>}, @result
166
+ end
167
+ end
168
+
169
+ context "using Redcarpet" do
170
+ setup do
171
+ create_post(@content, 'markdown' => 'redcarpet')
172
+ end
173
+
174
+ should "parse correctly" do
175
+ assert_match %r{<em>FIGHT!</em>}, @result
176
+ assert_match %r{<em>FINISH HIM</em>}, @result
177
+ end
178
+ end
179
+ end
180
+
181
+ context "simple page with post linking" do
182
+ setup do
183
+ content = <<CONTENT
184
+ ---
185
+ title: Post linking
186
+ ---
187
+
188
+ {% post_url 2008-11-21-complex %}
189
+ CONTENT
190
+ create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
191
+ end
192
+
193
+ should "not cause an error" do
194
+ assert_no_match /markdown\-html\-error/, @result
195
+ end
196
+
197
+ should "have the url to the \"complex\" post from 2008-11-21" do
198
+ assert_match %r{/2008/11/21/complex/}, @result
199
+ end
200
+ end
201
+ end