jekyll 0.5.7 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of jekyll might be problematic. Click here for more details.

Files changed (48) hide show
  1. data/History.txt +88 -31
  2. data/LICENSE +21 -0
  3. data/README.textile +1 -9
  4. data/Rakefile +119 -51
  5. data/bin/jekyll +26 -2
  6. data/cucumber.yml +1 -0
  7. data/features/create_sites.feature +28 -10
  8. data/features/post_data.feature +7 -7
  9. data/features/site_configuration.feature +41 -1
  10. data/features/step_definitions/jekyll_steps.rb +13 -4
  11. data/jekyll.gemspec +125 -143
  12. data/lib/jekyll.rb +40 -20
  13. data/lib/jekyll/albino.rb +5 -7
  14. data/lib/jekyll/converter.rb +50 -0
  15. data/lib/jekyll/converters/identity.rb +22 -0
  16. data/lib/jekyll/converters/markdown.rb +77 -0
  17. data/lib/jekyll/converters/textile.rb +33 -0
  18. data/lib/jekyll/convertible.rb +18 -24
  19. data/lib/jekyll/errors.rb +6 -0
  20. data/lib/jekyll/generator.rb +7 -0
  21. data/lib/jekyll/generators/pagination.rb +87 -0
  22. data/lib/jekyll/{converters → migrators}/csv.rb +0 -0
  23. data/lib/jekyll/{converters → migrators}/mephisto.rb +0 -0
  24. data/lib/jekyll/{converters → migrators}/mt.rb +0 -0
  25. data/lib/jekyll/{converters → migrators}/textpattern.rb +0 -0
  26. data/lib/jekyll/{converters → migrators}/typo.rb +0 -0
  27. data/lib/jekyll/{converters → migrators}/wordpress.rb +1 -0
  28. data/lib/jekyll/page.rb +28 -11
  29. data/lib/jekyll/plugin.rb +76 -0
  30. data/lib/jekyll/post.rb +10 -8
  31. data/lib/jekyll/site.rb +40 -88
  32. data/lib/jekyll/static_file.rb +52 -4
  33. data/lib/jekyll/tags/highlight.rb +20 -9
  34. data/test/helper.rb +6 -0
  35. data/test/source/_posts/2010-01-09-date-override.textile +2 -0
  36. data/test/source/_posts/2010-01-09-time-override.textile +2 -0
  37. data/test/source/_posts/2010-01-09-timezone-override.textile +7 -0
  38. data/test/source/_posts/2010-01-16-override-data.textile +4 -0
  39. data/test/source/sitemap.xml +27 -18
  40. data/test/test_configuration.rb +1 -1
  41. data/test/test_generated_site.rb +1 -1
  42. data/test/test_post.rb +63 -12
  43. data/test/test_site.rb +69 -7
  44. data/test/test_tags.rb +6 -14
  45. metadata +156 -52
  46. data/.gitignore +0 -6
  47. data/VERSION.yml +0 -5
  48. data/lib/jekyll/pager.rb +0 -45
@@ -4,15 +4,28 @@ module Jekyll
4
4
  include Liquid::StandardFilters
5
5
 
6
6
  # we need a language, but the linenos argument is optional.
7
- SYNTAX = /(\w+)\s?(:?linenos)?\s?/
7
+ SYNTAX = /(\w+)\s?([\w\s=]+)*/
8
8
 
9
9
  def initialize(tag_name, markup, tokens)
10
10
  super
11
11
  if markup =~ SYNTAX
12
12
  @lang = $1
13
13
  if defined? $2
14
+ tmp_options = {}
15
+ $2.split.each do |opt|
16
+ key, value = opt.split('=')
17
+ if value.nil?
18
+ if key == 'linenos'
19
+ value = 'inline'
20
+ else
21
+ value = true
22
+ end
23
+ end
24
+ tmp_options[key] = value
25
+ end
26
+ tmp_options = tmp_options.to_a.collect { |opt| opt.join('=') }
14
27
  # additional options to pass to Albino.
15
- @options = { 'O' => 'linenos=inline' }
28
+ @options = { 'O' => tmp_options.join(',') }
16
29
  else
17
30
  @options = {}
18
31
  end
@@ -23,19 +36,17 @@ module Jekyll
23
36
 
24
37
  def render(context)
25
38
  if context.registers[:site].pygments
26
- render_pygments(context, super.to_s)
39
+ render_pygments(context, super.join)
27
40
  else
28
- render_codehighlighter(context, super.to_s)
41
+ render_codehighlighter(context, super.join)
29
42
  end
30
43
  end
31
44
 
32
45
  def render_pygments(context, code)
33
46
  output = add_code_tags(Albino.new(code, @lang).to_s(@options), @lang)
34
- if context["content_type"] == "markdown"
35
- return "\n" + output + "\n"
36
- elsif context["content_type"] == "textile"
37
- return "<notextile>" + output + "</notextile>"
38
- end
47
+ output = context["pygments_prefix"] + output if context["pygments_prefix"]
48
+ output = output + context["pygments_suffix"] if context["pygments_suffix"]
49
+ output
39
50
  end
40
51
 
41
52
  def render_codehighlighter(context, code)
@@ -3,6 +3,9 @@ gem 'RedCloth', '>= 4.2.1'
3
3
 
4
4
  require File.join(File.dirname(__FILE__), *%w[.. lib jekyll])
5
5
 
6
+ require 'RedCloth'
7
+ require 'rdiscount'
8
+
6
9
  require 'test/unit'
7
10
  require 'redgreen'
8
11
  require 'shoulda'
@@ -10,6 +13,9 @@ require 'rr'
10
13
 
11
14
  include Jekyll
12
15
 
16
+ # Send STDERR into the void to suppress program output messages
17
+ STDERR.reopen(test(?e, '/dev/null') ? '/dev/null' : 'NUL:')
18
+
13
19
  class Test::Unit::TestCase
14
20
  include RR::Adapters::TestUnit
15
21
 
@@ -3,3 +3,5 @@ date: 2010-01-10
3
3
  ---
4
4
 
5
5
  Post with a front matter date
6
+
7
+ {{ page.date | date_to_string }}
@@ -3,3 +3,5 @@ date: 2010-01-10 13:07:09
3
3
  ---
4
4
 
5
5
  Post with a front matter time
6
+
7
+ {{ page.date | date_to_string }}
@@ -0,0 +1,7 @@
1
+ ---
2
+ date: 2010-01-10 13:07:09 +00:00
3
+ ---
4
+
5
+ Post with a front matter time with timezone
6
+
7
+ {{ page.date | date_to_string }}
@@ -0,0 +1,4 @@
1
+ ---
2
+ date: 2010-01-10 13:07:09
3
+ tags: A string
4
+ ---
@@ -2,22 +2,31 @@
2
2
  layout: nil
3
3
  ---
4
4
  <?xml version="1.0" encoding="UTF-8"?>
5
- <urlset
6
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
7
-
5
+ <urlset
6
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
7
+
8
8
  <url>
9
- <loc>http://example.com</loc>
10
- <lastmod>{{ site.time | date_to_xmlschema }}</lastmod>
11
- <changefreq>daily</changefreq>
12
- <priority>1.0</priority>
13
- </url>
14
-
15
- {% for post in site.posts %}
16
- <url>
17
- <loc>http://example.com/{{ post.url }}/</loc>
18
- <lastmod>{{ site.time }}</lastmod>
19
- <changefreq>monthly</changefreq>
20
- <priority>0.2</priority>
21
- </url>
22
- {% endfor %}
23
- </urlset>
9
+ <loc>http://example.com</loc>
10
+ <lastmod>{{ site.time | date: "%Y-%m-%d" }}</lastmod>
11
+ <changefreq>daily</changefreq>
12
+ <priority>1.0</priority>
13
+ </url>
14
+
15
+ {% for post in site.posts %}
16
+ <url>
17
+ <loc>http://example.com{{ post.url }}/</loc>
18
+ <lastmod>{{ post.date | date: "%Y-%m-%d" }}</lastmod>
19
+ <changefreq>monthly</changefreq>
20
+ <priority>0.2</priority>
21
+ </url>
22
+ {% endfor %}
23
+
24
+ {% for page in site.html_pages %}
25
+ <url>
26
+ <loc>http://example.com{{ page.url }}</loc>
27
+ <lastmod>{{ site.time | date: "%Y-%m-%d" }}</lastmod>
28
+ {% if page.changefreq %}<changefreq>{{ page.changefreq }}</changefreq>{% endif %}
29
+ {% if page.priority %}<priority>{{ page.priority }}</priority>{% endif %}
30
+ </url>
31
+ {% endfor %}
32
+ </urlset>
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + '/helper'
3
3
  class TestConfiguration < Test::Unit::TestCase
4
4
  context "loading configuration" do
5
5
  setup do
6
- @path = './_config.yml'
6
+ @path = File.join(Dir.pwd, '_config.yml')
7
7
  end
8
8
 
9
9
  should "fire warning with no _config.yml" do
@@ -14,7 +14,7 @@ class TestGeneratedSite < Test::Unit::TestCase
14
14
  end
15
15
 
16
16
  should "ensure post count is as expected" do
17
- assert_equal 24, @site.posts.size
17
+ assert_equal 26, @site.posts.size
18
18
  end
19
19
 
20
20
  should "insert site.posts into the index" do
@@ -18,10 +18,10 @@ class TestPost < Test::Unit::TestCase
18
18
  end
19
19
 
20
20
  should "ensure valid posts are valid" do
21
- assert Post.valid?("2008-10-19-foo-bar.textile")
22
- assert Post.valid?("foo/bar/2008-10-19-foo-bar.textile")
21
+ assert Post.valid?("2008-09-09-foo-bar.textile")
22
+ assert Post.valid?("foo/bar/2008-09-09-foo-bar.textile")
23
23
 
24
- assert !Post.valid?("lol2008-10-19-foo-bar.textile")
24
+ assert !Post.valid?("lol2008-09-09-foo-bar.textile")
25
25
  assert !Post.valid?("blah")
26
26
  end
27
27
 
@@ -31,7 +31,7 @@ class TestPost < Test::Unit::TestCase
31
31
  @post.site = @site
32
32
 
33
33
  @real_file = "2008-10-18-foo-bar.textile"
34
- @fake_file = "2008-10-19-foo-bar.textile"
34
+ @fake_file = "2008-09-09-foo-bar.textile"
35
35
  @source = source_dir('_posts')
36
36
  end
37
37
 
@@ -39,17 +39,17 @@ class TestPost < Test::Unit::TestCase
39
39
  @post.categories = []
40
40
  @post.process(@fake_file)
41
41
 
42
- assert_equal Time.parse("2008-10-19"), @post.date
42
+ assert_equal Time.parse("2008-09-09"), @post.date
43
43
  assert_equal "foo-bar", @post.slug
44
44
  assert_equal ".textile", @post.ext
45
- assert_equal "/2008/10/19", @post.dir
46
- assert_equal "/2008/10/19/foo-bar", @post.id
45
+ assert_equal "/2008/09/09", @post.dir
46
+ assert_equal "/2008/09/09/foo-bar", @post.id
47
47
  end
48
48
 
49
49
  should "create url based on date and title" do
50
50
  @post.categories = []
51
51
  @post.process(@fake_file)
52
- assert_equal "/2008/10/19/foo-bar.html", @post.url
52
+ assert_equal "/2008/09/09/foo-bar.html", @post.url
53
53
  end
54
54
 
55
55
  should "CGI escape urls" do
@@ -106,7 +106,7 @@ class TestPost < Test::Unit::TestCase
106
106
 
107
107
  should "process the url correctly" do
108
108
  assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
109
- assert_equal "/2008/10/19/foo-bar.html", @post.url
109
+ assert_equal "/2008/09/09/foo-bar.html", @post.url
110
110
  end
111
111
  end
112
112
 
@@ -118,7 +118,7 @@ class TestPost < Test::Unit::TestCase
118
118
 
119
119
  should "process the url correctly" do
120
120
  assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
121
- assert_equal "/beer/2008/10/19/foo-bar.html", @post.url
121
+ assert_equal "/beer/2008/09/09/foo-bar.html", @post.url
122
122
  end
123
123
  end
124
124
 
@@ -131,7 +131,7 @@ class TestPost < Test::Unit::TestCase
131
131
 
132
132
  should "process the url correctly" do
133
133
  assert_equal "/:categories/:year/:month/:day/:title.html", @post.template
134
- assert_equal "/beer/food/2008/10/19/foo-bar.html", @post.url
134
+ assert_equal "/food/beer/2008/09/09/foo-bar.html", @post.url
135
135
  end
136
136
  end
137
137
 
@@ -155,7 +155,18 @@ class TestPost < Test::Unit::TestCase
155
155
 
156
156
  should "process the url correctly" do
157
157
  assert_equal "/:categories/:year/:month/:day/:title/", @post.template
158
- assert_equal "/2008/10/19/foo-bar/", @post.url
158
+ assert_equal "/2008/09/09/foo-bar/", @post.url
159
+ end
160
+ end
161
+
162
+ context "with custom date permalink" do
163
+ setup do
164
+ @post.site.permalink_style = '/:categories/:year/:i_month/:i_day/:title/'
165
+ @post.process(@fake_file)
166
+ end
167
+
168
+ should "process the url correctly" do
169
+ assert_equal "/2008/9/9/foo-bar/", @post.url
159
170
  end
160
171
  end
161
172
 
@@ -227,12 +238,37 @@ class TestPost < Test::Unit::TestCase
227
238
 
228
239
  should "recognize date in yaml" do
229
240
  post = setup_post("2010-01-09-date-override.textile")
241
+ do_render(post)
242
+ assert_equal Time, post.date.class
243
+ assert_equal Time, post.to_liquid["date"].class
230
244
  assert_equal "/2010/01/10/date-override.html", post.url
245
+ assert_equal "<p>Post with a front matter date</p>\n<p>10 Jan 2010</p>", post.output
231
246
  end
232
247
 
233
248
  should "recognize time in yaml" do
234
249
  post = setup_post("2010-01-09-time-override.textile")
250
+ do_render(post)
251
+ assert_equal Time, post.date.class
252
+ assert_equal Time, post.to_liquid["date"].class
235
253
  assert_equal "/2010/01/10/time-override.html", post.url
254
+ assert_equal "<p>Post with a front matter time</p>\n<p>10 Jan 2010</p>", post.output
255
+ end
256
+
257
+ should "recognize time with timezone in yaml" do
258
+ post = setup_post("2010-01-09-timezone-override.textile")
259
+ do_render(post)
260
+ assert_equal Time, post.date.class
261
+ assert_equal Time, post.to_liquid["date"].class
262
+ assert_equal "/2010/01/10/timezone-override.html", post.url
263
+ assert_equal "<p>Post with a front matter time with timezone</p>\n<p>10 Jan 2010</p>", post.output
264
+ end
265
+
266
+ should "to_liquid prioritizes post attributes over data" do
267
+ post = setup_post("2010-01-16-override-data.textile")
268
+ assert_equal Array, post.tags.class
269
+ assert_equal Array, post.to_liquid["tags"].class
270
+ assert_equal Time, post.date.class
271
+ assert_equal Time, post.to_liquid["date"].class
236
272
  end
237
273
 
238
274
  should "recognize category in yaml" do
@@ -333,6 +369,21 @@ class TestPost < Test::Unit::TestCase
333
369
 
334
370
  assert_equal "<<< <hr />\n<p>Tom Preston-Werner github.com/mojombo</p>\n\n<p>This <em>is</em> cool</p> >>>", post.output
335
371
  end
372
+
373
+ should "render date specified in front matter properly" do
374
+ post = setup_post("2010-01-09-date-override.textile")
375
+ do_render(post)
376
+
377
+ assert_equal "<p>Post with a front matter date</p>\n<p>10 Jan 2010</p>", post.output
378
+ end
379
+
380
+ should "render time specified in front matter properly" do
381
+ post = setup_post("2010-01-09-time-override.textile")
382
+ do_render(post)
383
+
384
+ assert_equal "<p>Post with a front matter time</p>\n<p>10 Jan 2010</p>", post.output
385
+ end
386
+
336
387
  end
337
388
  end
338
389
 
@@ -22,6 +22,7 @@ class TestSite < Test::Unit::TestCase
22
22
  before_tags = @site.tags.length
23
23
  before_pages = @site.pages.length
24
24
  before_static_files = @site.static_files.length
25
+ before_time = @site.time
25
26
 
26
27
  @site.process
27
28
  assert_equal before_posts, @site.posts.length
@@ -30,6 +31,65 @@ class TestSite < Test::Unit::TestCase
30
31
  assert_equal before_tags, @site.tags.length
31
32
  assert_equal before_pages, @site.pages.length
32
33
  assert_equal before_static_files, @site.static_files.length
34
+ assert before_time <= @site.time
35
+ end
36
+
37
+ should "write only modified static files" do
38
+ clear_dest
39
+ StaticFile.reset_cache
40
+
41
+ @site.process
42
+ some_static_file = @site.static_files[0].path
43
+ dest = File.expand_path(@site.static_files[0].destination(@site.dest))
44
+ mtime1 = File.stat(dest).mtime.to_i # first run must generate dest file
45
+
46
+ # need to sleep because filesystem timestamps have best resolution in seconds
47
+ sleep 1
48
+ @site.process
49
+ mtime2 = File.stat(dest).mtime.to_i
50
+ assert_equal mtime1, mtime2
51
+
52
+ # simulate file modification by user
53
+ FileUtils.touch some_static_file
54
+
55
+ sleep 1
56
+ @site.process
57
+ mtime3 = File.stat(dest).mtime.to_i
58
+ assert_not_equal mtime2, mtime3 # must be regenerated!
59
+
60
+ sleep 1
61
+ @site.process
62
+ mtime4 = File.stat(dest).mtime.to_i
63
+ assert_equal mtime3, mtime4 # no modifications, so must be the same
64
+ end
65
+
66
+ should "write static files if not modified but missing in destination" do
67
+ clear_dest
68
+ StaticFile.reset_cache
69
+
70
+ @site.process
71
+ some_static_file = @site.static_files[0].path
72
+ dest = File.expand_path(@site.static_files[0].destination(@site.dest))
73
+ mtime1 = File.stat(dest).mtime.to_i # first run must generate dest file
74
+
75
+ # need to sleep because filesystem timestamps have best resolution in seconds
76
+ sleep 1
77
+ @site.process
78
+ mtime2 = File.stat(dest).mtime.to_i
79
+ assert_equal mtime1, mtime2
80
+
81
+ # simulate destination file deletion
82
+ File.unlink dest
83
+
84
+ sleep 1
85
+ @site.process
86
+ mtime3 = File.stat(dest).mtime.to_i
87
+ assert_not_equal mtime2, mtime3 # must be regenerated and differ!
88
+
89
+ sleep 1
90
+ @site.process
91
+ mtime4 = File.stat(dest).mtime.to_i
92
+ assert_equal mtime3, mtime4 # no modifications, so must be the same
33
93
  end
34
94
 
35
95
  should "read layouts" do
@@ -73,18 +133,20 @@ class TestSite < Test::Unit::TestCase
73
133
  end
74
134
 
75
135
  context 'with an invalid markdown processor in the configuration' do
76
-
77
- should 'give a meaningful error message' do
136
+ should 'not throw an error at initialization time' do
78
137
  bad_processor = 'not a processor name'
79
- begin
138
+ assert_nothing_raised do
80
139
  Site.new(Jekyll.configuration.merge({ 'markdown' => bad_processor }))
81
- flunk 'Invalid markdown processors should cause a failure on site creation'
82
- rescue RuntimeError => e
83
- assert e.to_s =~ /invalid|bad/i
84
- assert e.to_s =~ %r{#{bad_processor}}
85
140
  end
86
141
  end
87
142
 
143
+ should 'throw FatalException at process time' do
144
+ bad_processor = 'not a processor name'
145
+ s = Site.new(Jekyll.configuration.merge({ 'markdown' => bad_processor }))
146
+ assert_raise Jekyll::FatalException do
147
+ s.process
148
+ end
149
+ end
88
150
  end
89
151
 
90
152
  end
@@ -2,26 +2,18 @@ require File.dirname(__FILE__) + '/helper'
2
2
 
3
3
  class TestTags < Test::Unit::TestCase
4
4
 
5
- def create_post(content, override = {}, markdown = true)
5
+ def create_post(content, override = {}, converter_class = Jekyll::MarkdownConverter)
6
6
  stub(Jekyll).configuration do
7
7
  Jekyll::DEFAULTS.merge({'pygments' => true}).merge(override)
8
8
  end
9
9
  site = Site.new(Jekyll.configuration)
10
10
  info = { :filters => [Jekyll::Filters], :registers => { :site => site } }
11
-
12
- if markdown
13
- payload = {"content_type" => "markdown"}
14
- else
15
- payload = {"content_type" => "textile"}
16
- end
11
+ @converter = site.converters.find { |c| c.class == converter_class }
12
+ payload = { "pygments_prefix" => @converter.pygments_prefix,
13
+ "pygments_suffix" => @converter.pygments_suffix }
17
14
 
18
15
  @result = Liquid::Template.parse(content).render(payload, info)
19
-
20
- if markdown
21
- @result = site.markdown(@result)
22
- else
23
- @result = site.textile(@result)
24
- end
16
+ @result = @converter.convert(@result)
25
17
  end
26
18
 
27
19
  def fill_post(code, override = {})
@@ -82,7 +74,7 @@ CONTENT
82
74
 
83
75
  context "using Textile" do
84
76
  setup do
85
- create_post(@content, {}, false)
77
+ create_post(@content, {}, Jekyll::TextileConverter)
86
78
  end
87
79
 
88
80
  # Broken in RedCloth 4.1.9