jekyll 1.0.0.rc1 → 1.0.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 (72) hide show
  1. data/CONTRIBUTING.md +1 -1
  2. data/History.txt +15 -1
  3. data/Rakefile +0 -4
  4. data/bin/jekyll +3 -3
  5. data/features/pagination.feature +5 -5
  6. data/features/step_definitions/jekyll_steps.rb +1 -1
  7. data/jekyll.gemspec +9 -6
  8. data/lib/jekyll.rb +1 -2
  9. data/lib/jekyll/commands/new.rb +4 -0
  10. data/lib/jekyll/configuration.rb +3 -1
  11. data/lib/jekyll/converters/markdown/redcarpet_parser.rb +1 -0
  12. data/lib/jekyll/convertible.rb +66 -36
  13. data/lib/jekyll/deprecator.rb +9 -0
  14. data/lib/jekyll/filters.rb +17 -4
  15. data/lib/jekyll/generators/pagination.rb +17 -5
  16. data/lib/jekyll/logger.rb +3 -1
  17. data/lib/jekyll/page.rb +1 -13
  18. data/lib/jekyll/post.rb +67 -49
  19. data/lib/jekyll/site.rb +3 -3
  20. data/lib/jekyll/tags/highlight.rb +2 -0
  21. data/lib/jekyll/tags/post_url.rb +25 -7
  22. data/lib/site_template/.gitignore +1 -0
  23. data/lib/site_template/_config.yml +1 -0
  24. data/lib/site_template/_layouts/default.html +44 -36
  25. data/lib/site_template/_layouts/post.html +3 -0
  26. data/lib/site_template/css/main.css +165 -0
  27. data/site/_includes/docs_contents.html +4 -1
  28. data/site/_includes/docs_contents_mobile.html +36 -0
  29. data/site/_includes/footer.html +10 -10
  30. data/site/_includes/header.html +7 -15
  31. data/site/_includes/primary-nav-items.html +11 -0
  32. data/site/_includes/top.html +2 -1
  33. data/site/_layouts/default.html +1 -1
  34. data/site/_layouts/docs.html +4 -2
  35. data/site/_posts/2012-07-01-configuration.md +18 -8
  36. data/site/_posts/2012-07-01-contributing.md +22 -6
  37. data/site/_posts/2012-07-01-extras.md +3 -2
  38. data/site/_posts/2012-07-01-frontmatter.md +7 -2
  39. data/site/_posts/2012-07-01-home.md +4 -4
  40. data/site/_posts/2012-07-01-installation.md +6 -6
  41. data/site/_posts/2012-07-01-migrations.md +64 -23
  42. data/site/_posts/2012-07-01-pages.md +2 -2
  43. data/site/_posts/2012-07-01-pagination.md +6 -1
  44. data/site/_posts/2012-07-01-permalinks.md +6 -0
  45. data/site/_posts/2012-07-01-plugins.md +9 -1
  46. data/site/_posts/2012-07-01-resources.md +1 -4
  47. data/site/_posts/2012-07-01-structure.md +3 -1
  48. data/site/_posts/2012-07-01-templates.md +2 -1
  49. data/site/_posts/2012-07-01-troubleshooting.md +20 -2
  50. data/site/_posts/2012-07-01-upgrading.md +104 -0
  51. data/site/_posts/2012-07-01-usage.md +1 -1
  52. data/site/_posts/2012-07-01-variables.md +18 -9
  53. data/site/css/gridism.css +110 -0
  54. data/site/css/style.css +236 -101
  55. data/site/img/footer-logo.png +0 -0
  56. data/site/img/octojekyll.png +0 -0
  57. data/site/index.html +51 -43
  58. data/test/helper.rb +1 -0
  59. data/test/source/_posts/es/2008-11-21-nested.textile +8 -0
  60. data/test/test_convertible.rb +1 -1
  61. data/test/test_filters.rb +34 -11
  62. data/test/test_generated_site.rb +13 -2
  63. data/test/test_kramdown.rb +4 -2
  64. data/test/test_pager.rb +4 -2
  65. data/test/test_post.rb +2 -2
  66. data/test/test_site.rb +7 -6
  67. data/test/test_tags.rb +30 -0
  68. metadata +12 -12
  69. data/lib/site_template/css/screen.css +0 -189
  70. data/lib/site_template/images/.gitkeep +0 -0
  71. data/lib/site_template/images/rss.png +0 -0
  72. data/site/css/grid.css +0 -62
@@ -11,7 +11,7 @@ module Jekyll
11
11
  # Returns nothing.
12
12
  def generate(site)
13
13
  site.pages.dup.each do |page|
14
- paginate(site, page) if Pager.pagination_enabled?(site.config, page.name)
14
+ paginate(site, page) if Pager.pagination_enabled?(site.config, page)
15
15
  end
16
16
  end
17
17
 
@@ -65,11 +65,23 @@ module Jekyll
65
65
  # Determine if pagination is enabled for a given file.
66
66
  #
67
67
  # config - The configuration Hash.
68
- # file - The String filename of the file.
68
+ # page - The Jekyll::Page with which to paginate
69
69
  #
70
70
  # Returns true if pagination is enabled, false otherwise.
71
- def self.pagination_enabled?(config, file)
72
- file == 'index.html' && !config['paginate'].nil?
71
+ def self.pagination_enabled?(config, page)
72
+ !config['paginate'].nil? &&
73
+ page.name == 'index.html' &&
74
+ subdirectories_identical(config['paginate_path'], page.dir)
75
+ end
76
+
77
+ # Determine if the subdirectories of the two paths are the same relative to source
78
+ #
79
+ # paginate_path - the paginate_path configuration setting
80
+ # page_dir - the directory of the Jekyll::Page
81
+ #
82
+ # Returns whether the subdirectories are the same relative to source
83
+ def self.subdirectories_identical(paginate_path, page_dir)
84
+ File.dirname(paginate_path).gsub(/\A\./, '') == page_dir.gsub(/\/\z/, '')
73
85
  end
74
86
 
75
87
  # Static: Return the pagination path of the page
@@ -80,7 +92,7 @@ module Jekyll
80
92
  # Returns the pagination path as a string
81
93
  def self.paginate_path(site_config, num_page)
82
94
  return nil if num_page.nil? || num_page <= 1
83
- format = site_config['paginate_path']
95
+ format = File.basename(site_config['paginate_path'])
84
96
  format.sub(':num', num_page.to_s)
85
97
  end
86
98
 
@@ -1,5 +1,7 @@
1
+ require 'logger'
2
+
1
3
  module Jekyll
2
- module Logger
4
+ class Logger < Logger
3
5
  # Public: Print a jekyll message to stdout
4
6
  #
5
7
  # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
@@ -78,6 +78,7 @@ module Jekyll
78
78
  # sanitize url
79
79
  @url = url.split('/').reject{ |part| part =~ /^\.+$/ }.join('/')
80
80
  @url += "/" if url =~ /\/$/
81
+ @url.gsub!(/\A([^\/])/, '/\1')
81
82
  @url
82
83
  end
83
84
 
@@ -129,19 +130,6 @@ module Jekyll
129
130
  path
130
131
  end
131
132
 
132
- # Write the generated page file to the destination directory.
133
- #
134
- # dest - The String path to the destination dir.
135
- #
136
- # Returns nothing.
137
- def write(dest)
138
- path = destination(dest)
139
- FileUtils.mkdir_p(File.dirname(path))
140
- File.open(path, 'w') do |f|
141
- f.write(self.output)
142
- end
143
- end
144
-
145
133
  # Returns the object as a debug String.
146
134
  def inspect
147
135
  "#<Jekyll:Page @name=#{self.name.inspect}>"
@@ -10,6 +10,21 @@ module Jekyll
10
10
  # Valid post name regex.
11
11
  MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
12
12
 
13
+ # Attributes for Liquid templates
14
+ ATTRIBUTES_FOR_LIQUID = %w[
15
+ title
16
+ url
17
+ date
18
+ id
19
+ categories
20
+ next
21
+ previous
22
+ tags
23
+ content
24
+ excerpt
25
+ path
26
+ ]
27
+
13
28
  # Post name validator. Post filenames must be like:
14
29
  # 2008-11-05-my-awesome-post.textile
15
30
  #
@@ -39,35 +54,37 @@ module Jekyll
39
54
 
40
55
  self.categories = dir.downcase.split('/').reject { |x| x.empty? }
41
56
  self.process(name)
42
- begin
43
- self.read_yaml(@base, name)
44
- rescue Exception => msg
45
- raise FatalException.new("#{msg} in #{@base}/#{name}")
46
- end
57
+ self.read_yaml(@base, name)
47
58
 
48
- # If we've added a date and time to the YAML, use that instead of the
49
- # filename date. Means we'll sort correctly.
50
59
  if self.data.has_key?('date')
51
- # ensure Time via to_s and reparse
52
60
  self.date = Time.parse(self.data["date"].to_s)
53
61
  end
54
62
 
63
+ self.published = self.published?
64
+
65
+ self.populate_categories
66
+ self.populate_tags
67
+ end
68
+
69
+ def published?
55
70
  if self.data.has_key?('published') && self.data['published'] == false
56
- self.published = false
71
+ false
57
72
  else
58
- self.published = true
73
+ true
59
74
  end
75
+ end
60
76
 
61
- self.tags = self.data.pluralized_array("tag", "tags")
62
-
77
+ def populate_categories
63
78
  if self.categories.empty?
64
79
  self.categories = self.data.pluralized_array('category', 'categories').map {|c| c.downcase}
65
80
  end
66
-
67
- self.tags.flatten!
68
81
  self.categories.flatten!
69
82
  end
70
83
 
84
+ def populate_tags
85
+ self.tags = self.data.pluralized_array("tag", "tags").flatten
86
+ end
87
+
71
88
  # Get the full path to the directory containing the post files
72
89
  def containing_dir(source, dir)
73
90
  return File.join(source, dir, '_posts')
@@ -96,6 +113,23 @@ module Jekyll
96
113
  end
97
114
  end
98
115
 
116
+ # Public: the Post title, from the YAML Front-Matter or from the slug
117
+ #
118
+ # Returns the post title
119
+ def title
120
+ self.data["title"] || self.slug.split('-').select {|w| w.capitalize! || w }.join(' ')
121
+ end
122
+
123
+ # Public: the path to the post relative to the site source,
124
+ # from the YAML Front-Matter or from a combination of
125
+ # the directory it's in, "_posts", and the name of the
126
+ # post file
127
+ #
128
+ # Returns the path to the file relative to the site source
129
+ def path
130
+ self.data['path'] || File.join(@dir, '_posts', @name).sub(/\A\//, '')
131
+ end
132
+
99
133
  # Compares Post objects. First compares the Post date. If the dates are
100
134
  # equal, it compares the Post slugs.
101
135
  #
@@ -194,6 +228,7 @@ module Jekyll
194
228
  # sanitize url
195
229
  @url = url.split('/').reject{ |part| part =~ /^\.+$/ }.join('/')
196
230
  @url += "/" if url =~ /\/$/
231
+ @url.gsub!(/\A([^\/])/, '/\1')
197
232
  @url
198
233
  end
199
234
 
@@ -212,16 +247,7 @@ module Jekyll
212
247
  return [] unless posts.size > 1
213
248
 
214
249
  if self.site.lsi
215
- self.class.lsi ||= begin
216
- puts "Starting the classifier..."
217
- lsi = Classifier::LSI.new(:auto_rebuild => false)
218
- $stdout.print(" Populating LSI... ");$stdout.flush
219
- posts.each { |x| $stdout.print(".");$stdout.flush;lsi.add_item(x) }
220
- $stdout.print("\n Rebuilding LSI index... ")
221
- lsi.build_index
222
- puts ""
223
- lsi
224
- end
250
+ build_index
225
251
 
226
252
  related = self.class.lsi.find_related(self.content, 11)
227
253
  related - [self]
@@ -230,6 +256,19 @@ module Jekyll
230
256
  end
231
257
  end
232
258
 
259
+ def build_index
260
+ self.class.lsi ||= begin
261
+ puts "Starting the classifier..."
262
+ lsi = Classifier::LSI.new(:auto_rebuild => false)
263
+ $stdout.print(" Populating LSI... "); $stdout.flush
264
+ posts.each { |x| $stdout.print("."); $stdout.flush; lsi.add_item(x) }
265
+ $stdout.print("\n Rebuilding LSI index... ")
266
+ lsi.build_index
267
+ puts ""
268
+ lsi
269
+ end
270
+ end
271
+
233
272
  # Add any necessary layouts to this post.
234
273
  #
235
274
  # layouts - A Hash of {"name" => "layout"}.
@@ -258,35 +297,14 @@ module Jekyll
258
297
  path
259
298
  end
260
299
 
261
- # Write the generated post file to the destination directory.
262
- #
263
- # dest - The String path to the destination dir.
264
- #
265
- # Returns nothing.
266
- def write(dest)
267
- path = destination(dest)
268
- FileUtils.mkdir_p(File.dirname(path))
269
- File.open(path, 'w') do |f|
270
- f.write(self.output)
271
- end
272
- end
273
-
274
300
  # Convert this post into a Hash for use in Liquid templates.
275
301
  #
276
302
  # Returns the representative Hash.
277
303
  def to_liquid
278
- self.data.deep_merge({
279
- "title" => self.data["title"] || self.slug.split('-').select {|w| w.capitalize! || w }.join(' '),
280
- "url" => self.url,
281
- "date" => self.date,
282
- "id" => self.id,
283
- "categories" => self.categories,
284
- "next" => self.next,
285
- "previous" => self.previous,
286
- "tags" => self.tags,
287
- "content" => self.content,
288
- "excerpt" => self.excerpt,
289
- "path" => self.data['path'] || File.join(@dir, '_posts', @name).sub(/\A\//, '') })
304
+ further_data = Hash[ATTRIBUTES_FOR_LIQUID.map { |attribute|
305
+ [attribute, send(attribute)]
306
+ }]
307
+ data.deep_merge(further_data)
290
308
  end
291
309
 
292
310
  # Returns the shorthand String identifier of this Post.
@@ -62,8 +62,8 @@ module Jekyll
62
62
  self.categories = Hash.new { |hash, key| hash[key] = [] }
63
63
  self.tags = Hash.new { |hash, key| hash[key] = [] }
64
64
 
65
- if !self.limit_posts.nil? && self.limit_posts < 1
66
- raise ArgumentError, "Limit posts must be nil or >= 1"
65
+ if self.limit_posts < 0
66
+ raise ArgumentError, "limit_posts must be a non-negative number"
67
67
  end
68
68
  end
69
69
 
@@ -148,7 +148,7 @@ module Jekyll
148
148
  self.posts.sort!
149
149
 
150
150
  # limit the posts if :limit_posts option is set
151
- if limit_posts
151
+ if limit_posts > 0
152
152
  limit = self.posts.length < limit_posts ? self.posts.length : limit_posts
153
153
  self.posts = self.posts[-limit, limit]
154
154
  end
@@ -49,6 +49,8 @@ eos
49
49
  end
50
50
 
51
51
  def render_pygments(context, code)
52
+ require 'pygments'
53
+
52
54
  @options[:encoding] = 'utf-8'
53
55
 
54
56
  output = add_code_tags(
@@ -6,10 +6,32 @@ module Jekyll
6
6
  attr_accessor :date, :slug
7
7
 
8
8
  def initialize(name)
9
- who, cares, date, slug = *name.match(MATCHER)
10
- @slug = slug
9
+ all, path, date, slug = *name.sub(/^\//, "").match(MATCHER)
10
+ @slug = path ? path + slug : slug
11
11
  @date = Time.parse(date)
12
12
  end
13
+
14
+ def ==(other)
15
+ slug == post_slug(other) &&
16
+ date.year == other.date.year &&
17
+ date.month == other.date.month &&
18
+ date.day == other.date.day
19
+ end
20
+
21
+ private
22
+ # Construct the directory-aware post slug for a Jekyll::Post
23
+ #
24
+ # other - the Jekyll::Post
25
+ #
26
+ # Returns the post slug with the subdirectory (relative to _posts)
27
+ def post_slug(other)
28
+ path = other.name.split("/")[0...-1].join("/")
29
+ if path.nil? || path == ""
30
+ other.slug
31
+ else
32
+ path + '/' + other.slug
33
+ end
34
+ end
13
35
  end
14
36
 
15
37
  class PostUrl < Liquid::Tag
@@ -23,11 +45,7 @@ module Jekyll
23
45
  site = context.registers[:site]
24
46
 
25
47
  site.posts.each do |p|
26
- if p.slug == @post.slug \
27
- and p.date.year == @post.date.year \
28
- and p.date.month == @post.date.month \
29
- and p.date.day == @post.date.day
30
-
48
+ if @post == p
31
49
  return p.url
32
50
  end
33
51
  end
@@ -0,0 +1 @@
1
+ _site
@@ -1 +1,2 @@
1
+ name: Your New Jekyll Site
1
2
  pygments: true
@@ -1,38 +1,46 @@
1
1
  <!DOCTYPE html>
2
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us">
3
- <head>
4
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
5
- <title>{{ page.title }}</title>
6
- <!-- syntax highlighting CSS -->
7
- <link rel="stylesheet" href="/css/syntax.css" type="text/css" />
8
- <!-- Homepage CSS -->
9
- <link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen, projection" />
10
- </head>
11
- <body>
12
- <div class="site">
13
- <div class="title">
14
- <a href="/">Your Name</a>
15
- <a class="extra" href="/">home</a>
16
- </div>
17
-
18
- {{ content }}
19
-
20
- <div class="footer">
21
- <div class="contact">
22
- <p>
23
- Your Name<br />
24
- What You Are<br />
25
- your@email.com
26
- </p>
27
- </div>
28
- <div class="contact">
29
- <p>
30
- <a href="http://github.com/yourusername/">github.com/yourusername</a><br />
31
- <a href="http://twitter.com/yourusername/">twitter.com/yourusername</a><br />
32
- </p>
33
- </div>
34
- </div>
35
- </div>
36
- <a href="http://github.com/yourusername"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub" /></a>
37
- </body>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
6
+ <title>{{ page.title }}</title>
7
+ <meta name="viewport" content="width=device-width">
8
+
9
+ <!-- syntax highlighting CSS -->
10
+ <link rel="stylesheet" href="/css/syntax.css">
11
+
12
+ <!-- Custom CSS -->
13
+ <link rel="stylesheet" href="/css/main.css">
14
+
15
+ </head>
16
+ <body>
17
+
18
+ <div class="container">
19
+ <div class="site">
20
+ <div class="header">
21
+ <h1 class="title"><a href="/">{{ site.name }}</a></h1>
22
+ <a class="extra" href="/">home</a>
23
+ </div>
24
+
25
+ {{ content }}
26
+
27
+ <div class="footer">
28
+ <div class="contact">
29
+ <p>
30
+ Your Name<br />
31
+ What You Are<br />
32
+ your@email.com
33
+ </p>
34
+ </div>
35
+ <div class="contact">
36
+ <p>
37
+ <a href="http://github.com/yourusername/">github.com/yourusername</a><br />
38
+ <a href="http://twitter.com/yourusername/">twitter.com/yourusername</a><br />
39
+ </p>
40
+ </div>
41
+ </div>
42
+
43
+ </div> <!-- /container -->
44
+
45
+ </body>
38
46
  </html>
@@ -1,6 +1,9 @@
1
1
  ---
2
2
  layout: default
3
3
  ---
4
+ <h2>{{ page.title }}</h2>
5
+ <p class="meta">{{ page.date | date_to_string }}</p>
6
+
4
7
  <div id="post">
5
8
  {{ content }}
6
9
  </div>
@@ -0,0 +1,165 @@
1
+ /*****************************************************************************/
2
+ /*
3
+ /* Common
4
+ /*
5
+ /*****************************************************************************/
6
+
7
+ /* Global Reset */
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ }
12
+
13
+ html, body { height: 100%; }
14
+
15
+ body {
16
+ background-color: #FFF;
17
+ font: 13.34px Helvetica, Arial, sans-serif;
18
+ font-size: small;
19
+ text-align: center;
20
+ }
21
+
22
+ h1, h2, h3, h4, h5, h6 {
23
+ font-size: 100%; }
24
+
25
+ h1 { margin-bottom: 1em; }
26
+ p { margin: 1em 0; }
27
+
28
+ a { color: #00a; }
29
+ a:hover { color: #000; }
30
+ a:visited { color: #a0a; }
31
+
32
+ table {
33
+ font-size: inherit;
34
+ font: 100%;
35
+ }
36
+
37
+ /*****************************************************************************/
38
+ /*
39
+ /* Home
40
+ /*
41
+ /*****************************************************************************/
42
+ ul.posts {
43
+ list-style-type: none;
44
+ margin-bottom: 2em;
45
+ }
46
+
47
+ ul.posts li {
48
+ line-height: 1.75em;
49
+ }
50
+
51
+ ul.posts span {
52
+ color: #aaa;
53
+ font-family: Monaco, "Courier New", monospace;
54
+ font-size: 80%;
55
+ }
56
+
57
+ /*****************************************************************************/
58
+ /*
59
+ /* Site
60
+ /*
61
+ /*****************************************************************************/
62
+
63
+ .site {
64
+ font-size: 115%;
65
+ text-align: justify;
66
+ width: 42em;
67
+ margin: 3em auto 2em;
68
+ line-height: 1.5em;
69
+ }
70
+
71
+ .site .header a {
72
+ font-weight: bold;
73
+ text-decoration: none;
74
+ }
75
+
76
+ .site .header h1.title {
77
+ display: inline-block;
78
+ margin-bottom: 2em;
79
+ }
80
+
81
+ .site .header h1.title a {
82
+ color: #a00;
83
+ }
84
+
85
+ .site .header h1.title a:hover {
86
+ color: #000;
87
+ }
88
+
89
+ .site .header a.extra {
90
+ color: #aaa;
91
+ margin-left: 1em;
92
+ }
93
+
94
+ .site .header a.extra:hover {
95
+ color: #000;
96
+ }
97
+
98
+ .site .meta {
99
+ color: #aaa;
100
+ }
101
+
102
+ .site .footer {
103
+ font-size: 80%;
104
+ color: #666;
105
+ border-top: 4px solid #eee;
106
+ margin-top: 2em;
107
+ overflow: hidden;
108
+ }
109
+
110
+ .site .footer .contact {
111
+ float: left;
112
+ margin-right: 3em;
113
+ }
114
+
115
+ .site .footer .contact a {
116
+ color: #8085C1;
117
+ }
118
+
119
+ .site .footer .rss {
120
+ margin-top: 1.1em;
121
+ margin-right: -.2em;
122
+ float: right;
123
+ }
124
+
125
+ .site .footer .rss img {
126
+ border: 0;
127
+ }
128
+
129
+ /*****************************************************************************/
130
+ /*
131
+ /* Posts
132
+ /*
133
+ /*****************************************************************************/
134
+
135
+ /* standard */
136
+ #post pre {
137
+ border: 1px solid #ddd;
138
+ background-color: #eef;
139
+ padding: 0 .4em;
140
+ }
141
+
142
+ #post ul, #post ol {
143
+ margin-left: 1.35em;
144
+ }
145
+
146
+ #post code {
147
+ border: 1px solid #ddd;
148
+ background-color: #eef;
149
+ padding: 0 .2em;
150
+ }
151
+
152
+ #post pre code {
153
+ border: none;
154
+ }
155
+
156
+ /* terminal */
157
+ #post pre.terminal {
158
+ border: 1px solid #000;
159
+ background-color: #333;
160
+ color: #FFF;
161
+ }
162
+
163
+ #post pre.terminal code {
164
+ background-color: #333;
165
+ }