jekyll 1.0.4 → 1.1.1
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.
- checksums.yaml +14 -6
- data/{CONTRIBUTING.md → CONTRIBUTING.markdown} +19 -1
- data/History.markdown +172 -85
- data/README.markdown +45 -0
- data/Rakefile +43 -18
- data/bin/jekyll +31 -1
- data/features/create_sites.feature +18 -0
- data/features/include_tag.feature +35 -0
- data/features/pagination.feature +28 -0
- data/features/post_excerpts.feature +50 -0
- data/features/step_definitions/jekyll_steps.rb +27 -11
- data/features/support/env.rb +9 -0
- data/jekyll.gemspec +32 -7
- data/lib/jekyll.rb +2 -1
- data/lib/jekyll/commands/new.rb +15 -3
- data/lib/jekyll/configuration.rb +23 -22
- data/lib/jekyll/converters/markdown/kramdown_parser.rb +4 -15
- data/lib/jekyll/convertible.rb +4 -0
- data/lib/jekyll/core_ext.rb +11 -0
- data/lib/jekyll/excerpt.rb +113 -0
- data/lib/jekyll/generators/pagination.rb +93 -23
- data/lib/jekyll/page.rb +1 -3
- data/lib/jekyll/post.rb +15 -55
- data/lib/jekyll/related_posts.rb +2 -1
- data/lib/jekyll/site.rb +33 -41
- data/lib/jekyll/stevenson.rb +25 -4
- data/lib/jekyll/tags/include.rb +46 -2
- data/lib/site_template/_config.yml +1 -0
- data/lib/site_template/css/main.css +0 -5
- data/site/_config.yml +1 -0
- data/site/_includes/docs_contents.html +12 -3
- data/site/_includes/docs_contents_mobile.html +7 -1
- data/site/_includes/news_contents.html +23 -0
- data/site/_includes/news_contents_mobile.html +11 -0
- data/site/_includes/news_item.html +24 -0
- data/site/_includes/primary-nav-items.html +4 -1
- data/site/_includes/top.html +2 -0
- data/site/_layouts/news.html +19 -0
- data/site/_layouts/news_item.html +27 -0
- data/site/_posts/2013-05-06-jekyll-1-0-0-released.markdown +23 -0
- data/site/_posts/2013-05-08-jekyll-1-0-1-released.markdown +27 -0
- data/site/_posts/2013-05-12-jekyll-1-0-2-released.markdown +28 -0
- data/site/_posts/2013-06-07-jekyll-1-0-3-released.markdown +25 -0
- data/site/_posts/2013-07-14-jekyll-1-1-0-released.markdown +27 -0
- data/site/_posts/2013-07-24-jekyll-1-1-1-released.markdown +31 -0
- data/site/css/style.css +125 -17
- data/site/docs/configuration.md +10 -1
- data/site/docs/contributing.md +21 -3
- data/site/docs/deployment-methods.md +2 -2
- data/site/docs/drafts.md +20 -0
- data/site/docs/extras.md +24 -3
- data/site/docs/github-pages.md +25 -0
- data/site/docs/history.md +150 -85
- data/site/docs/index.md +1 -17
- data/site/docs/installation.md +3 -2
- data/site/docs/migrations.md +2 -2
- data/site/docs/pagination.md +12 -0
- data/site/docs/plugins.md +97 -76
- data/site/docs/quickstart.md +32 -0
- data/site/docs/resources.md +0 -1
- data/site/docs/structure.md +15 -0
- data/site/docs/templates.md +26 -4
- data/site/docs/troubleshooting.md +22 -7
- data/site/docs/upgrading.md +6 -1
- data/site/docs/variables.md +12 -2
- data/site/feed.xml +36 -0
- data/site/freenode.txt +1 -0
- data/site/img/article-footer.png +0 -0
- data/site/img/footer-arrow.png +0 -0
- data/site/img/footer-logo.png +0 -0
- data/site/img/logo-2x.png +0 -0
- data/site/img/octojekyll.png +0 -0
- data/site/img/tube.png +0 -0
- data/site/img/tube1x.png +0 -0
- data/site/index.html +1 -1
- data/site/news/index.md +10 -0
- data/site/news/releases/index.md +10 -0
- data/test/source/+/foo.md +7 -0
- data/test/source/_includes/params.html +7 -0
- data/test/source/_posts/2013-07-22-post-excerpt-with-layout.markdown +23 -0
- data/test/test_configuration.rb +9 -0
- data/test/test_excerpt.rb +62 -0
- data/test/test_generated_site.rb +1 -1
- data/test/test_page.rb +9 -0
- data/test/test_pager.rb +31 -37
- data/test/test_post.rb +2 -1
- data/test/test_related_posts.rb +6 -1
- data/test/test_tags.rb +90 -0
- metadata +62 -23
- data/README.textile +0 -45
data/lib/jekyll/page.rb
CHANGED
@@ -134,9 +134,7 @@ module Jekyll
|
|
134
134
|
#
|
135
135
|
# Returns the destination file path String.
|
136
136
|
def destination(dest)
|
137
|
-
|
138
|
-
# filename.
|
139
|
-
path = File.join(dest, CGI.unescape(self.url))
|
137
|
+
path = File.join(dest, self.url)
|
140
138
|
path = File.join(path, "index.html") if self.url =~ /\/$/
|
141
139
|
path
|
142
140
|
end
|
data/lib/jekyll/post.rb
CHANGED
@@ -10,8 +10,7 @@ module Jekyll
|
|
10
10
|
# Valid post name regex.
|
11
11
|
MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
|
12
12
|
|
13
|
-
|
14
|
-
ATTRIBUTES_FOR_LIQUID = %w[
|
13
|
+
EXCERPT_ATTRIBUTES_FOR_LIQUID = %w[
|
15
14
|
title
|
16
15
|
url
|
17
16
|
date
|
@@ -20,11 +19,15 @@ module Jekyll
|
|
20
19
|
next
|
21
20
|
previous
|
22
21
|
tags
|
23
|
-
content
|
24
|
-
excerpt
|
25
22
|
path
|
26
23
|
]
|
27
24
|
|
25
|
+
# Attributes for Liquid templates
|
26
|
+
ATTRIBUTES_FOR_LIQUID = EXCERPT_ATTRIBUTES_FOR_LIQUID.concat(%w[
|
27
|
+
content
|
28
|
+
excerpt
|
29
|
+
])
|
30
|
+
|
28
31
|
# Post name validator. Post filenames must be like:
|
29
32
|
# 2008-11-05-my-awesome-post.textile
|
30
33
|
#
|
@@ -109,7 +112,7 @@ module Jekyll
|
|
109
112
|
if self.data.has_key? 'excerpt'
|
110
113
|
self.data['excerpt']
|
111
114
|
else
|
112
|
-
self.extracted_excerpt
|
115
|
+
self.extracted_excerpt.to_s
|
113
116
|
end
|
114
117
|
end
|
115
118
|
|
@@ -158,14 +161,6 @@ module Jekyll
|
|
158
161
|
raise FatalException.new("Post #{name} does not have a valid date.")
|
159
162
|
end
|
160
163
|
|
161
|
-
# Transform the contents and excerpt based on the content type.
|
162
|
-
#
|
163
|
-
# Returns nothing.
|
164
|
-
def transform
|
165
|
-
super
|
166
|
-
self.extracted_excerpt = converter.convert(self.extracted_excerpt)
|
167
|
-
end
|
168
|
-
|
169
164
|
# The generated directory into which the post will be placed
|
170
165
|
# upon generation. This is derived from the permalink or, if
|
171
166
|
# permalink is absent, set to the default date
|
@@ -257,10 +252,12 @@ module Jekyll
|
|
257
252
|
# construct payload
|
258
253
|
payload = {
|
259
254
|
"site" => { "related_posts" => related_posts(site_payload["site"]["posts"]) },
|
260
|
-
"page" => self.to_liquid
|
255
|
+
"page" => self.to_liquid(EXCERPT_ATTRIBUTES_FOR_LIQUID)
|
261
256
|
}.deep_merge(site_payload)
|
262
257
|
|
263
|
-
do_layout(payload,
|
258
|
+
self.extracted_excerpt.do_layout(payload, {})
|
259
|
+
|
260
|
+
do_layout(payload.merge({"page" => self.to_liquid}), layouts)
|
264
261
|
end
|
265
262
|
|
266
263
|
# Obtain destination path.
|
@@ -278,8 +275,8 @@ module Jekyll
|
|
278
275
|
# Convert this post into a Hash for use in Liquid templates.
|
279
276
|
#
|
280
277
|
# Returns the representative Hash.
|
281
|
-
def to_liquid
|
282
|
-
further_data = Hash[
|
278
|
+
def to_liquid(attrs = ATTRIBUTES_FOR_LIQUID)
|
279
|
+
further_data = Hash[attrs.map { |attribute|
|
283
280
|
[attribute, send(attribute)]
|
284
281
|
}]
|
285
282
|
data.deep_merge(further_data)
|
@@ -311,45 +308,8 @@ module Jekyll
|
|
311
308
|
|
312
309
|
protected
|
313
310
|
|
314
|
-
# Internal: Extract excerpt from the content
|
315
|
-
#
|
316
|
-
# By default excerpt is your first paragraph of a post: everything before
|
317
|
-
# the first two new lines:
|
318
|
-
#
|
319
|
-
# ---
|
320
|
-
# title: Example
|
321
|
-
# ---
|
322
|
-
#
|
323
|
-
# First paragraph with [link][1].
|
324
|
-
#
|
325
|
-
# Second paragraph.
|
326
|
-
#
|
327
|
-
# [1]: http://example.com/
|
328
|
-
#
|
329
|
-
# This is fairly good option for Markdown and Textile files. But might cause
|
330
|
-
# problems for HTML posts (which is quite unusual for Jekyll). If default
|
331
|
-
# excerpt delimiter is not good for you, you might want to set your own via
|
332
|
-
# configuration option `excerpt_separator`. For example, following is a good
|
333
|
-
# alternative for HTML posts:
|
334
|
-
#
|
335
|
-
# # file: _config.yml
|
336
|
-
# excerpt_separator: "<!-- more -->"
|
337
|
-
#
|
338
|
-
# Notice that all markdown-style link references will be appended to the
|
339
|
-
# excerpt. So the example post above will have this excerpt source:
|
340
|
-
#
|
341
|
-
# First paragraph with [link][1].
|
342
|
-
#
|
343
|
-
# [1]: http://example.com/
|
344
|
-
#
|
345
|
-
# Excerpts are rendered same time as content is rendered.
|
346
|
-
#
|
347
|
-
# Returns excerpt String
|
348
311
|
def extract_excerpt
|
349
|
-
|
350
|
-
head, _, tail = self.content.partition(separator)
|
351
|
-
|
352
|
-
"" << head << "\n\n" << tail.scan(/^\[[^\]]+\]:.+$/).join("\n")
|
312
|
+
Jekyll::Excerpt.new(self)
|
353
313
|
end
|
354
314
|
end
|
355
315
|
end
|
data/lib/jekyll/related_posts.rb
CHANGED
data/lib/jekyll/site.rb
CHANGED
@@ -138,34 +138,19 @@ module Jekyll
|
|
138
138
|
entries = Dir.chdir(base) { filter_entries(Dir.entries('.')) }
|
139
139
|
|
140
140
|
self.read_posts(dir)
|
141
|
-
|
142
|
-
if self.show_drafts
|
143
|
-
self.read_drafts(dir)
|
144
|
-
end
|
145
|
-
|
141
|
+
self.read_drafts(dir) if self.show_drafts
|
146
142
|
self.posts.sort!
|
147
|
-
|
148
|
-
# limit the posts if :limit_posts option is set
|
149
|
-
if limit_posts > 0
|
150
|
-
limit = self.posts.length < limit_posts ? self.posts.length : limit_posts
|
151
|
-
self.posts = self.posts[-limit, limit]
|
152
|
-
end
|
143
|
+
limit_posts! if limit_posts > 0 # limit the posts if :limit_posts option is set
|
153
144
|
|
154
145
|
entries.each do |f|
|
155
146
|
f_abs = File.join(base, f)
|
156
|
-
f_rel = File.join(dir, f)
|
157
147
|
if File.directory?(f_abs)
|
158
|
-
|
159
|
-
read_directories(f_rel)
|
148
|
+
f_rel = File.join(dir, f)
|
149
|
+
read_directories(f_rel) unless self.dest.sub(/\/$/, '') == f_abs
|
150
|
+
elsif has_yaml_header?(f_abs)
|
151
|
+
pages << Page.new(self, self.source, dir, f)
|
160
152
|
else
|
161
|
-
|
162
|
-
if first3 == "---"
|
163
|
-
# file appears to have a YAML header so process it as a page
|
164
|
-
pages << Page.new(self, self.source, dir, f)
|
165
|
-
else
|
166
|
-
# otherwise treat it as a static file
|
167
|
-
static_files << StaticFile.new(self, self.source, dir, f)
|
168
|
-
end
|
153
|
+
static_files << StaticFile.new(self, self.source, dir, f)
|
169
154
|
end
|
170
155
|
end
|
171
156
|
end
|
@@ -255,22 +240,18 @@ module Jekyll
|
|
255
240
|
|
256
241
|
# files to be written
|
257
242
|
files = Set.new
|
258
|
-
|
259
|
-
files << post.destination(self.dest)
|
260
|
-
end
|
261
|
-
self.pages.each do |page|
|
262
|
-
files << page.destination(self.dest)
|
263
|
-
end
|
264
|
-
self.static_files.each do |sf|
|
265
|
-
files << sf.destination(self.dest)
|
266
|
-
end
|
243
|
+
each_site_file { |item| files << item.destination(self.dest) }
|
267
244
|
|
268
245
|
# adding files' parent directories
|
269
246
|
dirs = Set.new
|
270
247
|
files.each { |file| dirs << File.dirname(file) }
|
271
248
|
files.merge(dirs)
|
272
249
|
|
273
|
-
|
250
|
+
# files that are replaced by dirs should be deleted
|
251
|
+
files_to_delete = Set.new
|
252
|
+
dirs.each { |dir| files_to_delete << dir if File.file?(dir) }
|
253
|
+
|
254
|
+
obsolete_files = dest_files - files + files_to_delete
|
274
255
|
FileUtils.rm_rf(obsolete_files.to_a)
|
275
256
|
end
|
276
257
|
|
@@ -290,15 +271,7 @@ module Jekyll
|
|
290
271
|
#
|
291
272
|
# Returns nothing.
|
292
273
|
def write
|
293
|
-
|
294
|
-
post.write(self.dest)
|
295
|
-
end
|
296
|
-
self.pages.each do |page|
|
297
|
-
page.write(self.dest)
|
298
|
-
end
|
299
|
-
self.static_files.each do |sf|
|
300
|
-
sf.write(self.dest)
|
301
|
-
end
|
274
|
+
each_site_file { |item| item.write(self.dest) }
|
302
275
|
end
|
303
276
|
|
304
277
|
# Construct a Hash of Posts indexed by the specified Post attribute.
|
@@ -430,5 +403,24 @@ module Jekyll
|
|
430
403
|
@deprecated_relative_permalinks = true
|
431
404
|
end
|
432
405
|
end
|
406
|
+
|
407
|
+
def each_site_file
|
408
|
+
%w(posts pages static_files).each do |type|
|
409
|
+
self.send(type).each do |item|
|
410
|
+
yield item
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
private
|
416
|
+
|
417
|
+
def has_yaml_header?(file)
|
418
|
+
"---" == File.open(file) { |fd| fd.read(3) }
|
419
|
+
end
|
420
|
+
|
421
|
+
def limit_posts!
|
422
|
+
limit = self.posts.length < limit_posts ? self.posts.length : limit_posts
|
423
|
+
self.posts = self.posts[-limit, limit]
|
424
|
+
end
|
433
425
|
end
|
434
426
|
end
|
data/lib/jekyll/stevenson.rb
CHANGED
@@ -5,7 +5,7 @@ module Jekyll
|
|
5
5
|
DEBUG = 0
|
6
6
|
INFO = 1
|
7
7
|
WARN = 2
|
8
|
-
ERROR
|
8
|
+
ERROR = 3
|
9
9
|
|
10
10
|
# Public: Create a new instance of Stevenson, Jekyll's logger
|
11
11
|
#
|
@@ -15,6 +15,16 @@ module Jekyll
|
|
15
15
|
def initialize(level = INFO)
|
16
16
|
@log_level = level
|
17
17
|
end
|
18
|
+
|
19
|
+
# Public: Print a jekyll debug message to stdout
|
20
|
+
#
|
21
|
+
# topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
|
22
|
+
# message - the message detail
|
23
|
+
#
|
24
|
+
# Returns nothing
|
25
|
+
def debug(topic, message = nil)
|
26
|
+
$stdout.puts(message(topic, message)) if log_level <= DEBUG
|
27
|
+
end
|
18
28
|
|
19
29
|
# Public: Print a jekyll message to stdout
|
20
30
|
#
|
@@ -22,7 +32,7 @@ module Jekyll
|
|
22
32
|
# message - the message detail
|
23
33
|
#
|
24
34
|
# Returns nothing
|
25
|
-
def info(topic, message)
|
35
|
+
def info(topic, message = nil)
|
26
36
|
$stdout.puts(message(topic, message)) if log_level <= INFO
|
27
37
|
end
|
28
38
|
|
@@ -32,7 +42,7 @@ module Jekyll
|
|
32
42
|
# message - the message detail
|
33
43
|
#
|
34
44
|
# Returns nothing
|
35
|
-
def warn(topic, message)
|
45
|
+
def warn(topic, message = nil)
|
36
46
|
$stderr.puts(message(topic, message).yellow) if log_level <= WARN
|
37
47
|
end
|
38
48
|
|
@@ -42,10 +52,21 @@ module Jekyll
|
|
42
52
|
# message - the message detail
|
43
53
|
#
|
44
54
|
# Returns nothing
|
45
|
-
def error(topic, message)
|
55
|
+
def error(topic, message = nil)
|
46
56
|
$stderr.puts(message(topic, message).red) if log_level <= ERROR
|
47
57
|
end
|
48
58
|
|
59
|
+
# Public: Print a Jekyll error message to stderr and immediately abort the process
|
60
|
+
#
|
61
|
+
# topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
|
62
|
+
# message - the message detail (can be omitted)
|
63
|
+
#
|
64
|
+
# Returns nothing
|
65
|
+
def abort_with(topic, message = nil)
|
66
|
+
error(topic, message)
|
67
|
+
abort
|
68
|
+
end
|
69
|
+
|
49
70
|
# Public: Build a Jekyll topic method
|
50
71
|
#
|
51
72
|
# topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
|
data/lib/jekyll/tags/include.rb
CHANGED
@@ -1,9 +1,51 @@
|
|
1
1
|
module Jekyll
|
2
2
|
module Tags
|
3
3
|
class IncludeTag < Liquid::Tag
|
4
|
-
|
4
|
+
|
5
|
+
MATCHER = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/
|
6
|
+
|
7
|
+
def initialize(tag_name, markup, tokens)
|
5
8
|
super
|
6
|
-
@file =
|
9
|
+
@file, @params = markup.strip.split(' ', 2);
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse_params(context)
|
13
|
+
validate_syntax
|
14
|
+
|
15
|
+
params = {}
|
16
|
+
markup = @params
|
17
|
+
|
18
|
+
while match = MATCHER.match(markup) do
|
19
|
+
markup = markup[match.end(0)..-1]
|
20
|
+
|
21
|
+
value = if match[2]
|
22
|
+
match[2].gsub(/\\"/, '"')
|
23
|
+
elsif match[3]
|
24
|
+
match[3].gsub(/\\'/, "'")
|
25
|
+
elsif match[4]
|
26
|
+
context[match[4]]
|
27
|
+
end
|
28
|
+
|
29
|
+
params[match[1]] = value
|
30
|
+
end
|
31
|
+
params
|
32
|
+
end
|
33
|
+
|
34
|
+
# ensure the entire markup string from start to end is valid syntax, and params are separated by spaces
|
35
|
+
def validate_syntax
|
36
|
+
full_matcher = Regexp.compile('\A\s*(?:' + MATCHER.to_s + '(?=\s|\z)\s*)*\z')
|
37
|
+
unless @params =~ full_matcher
|
38
|
+
raise SyntaxError.new <<-eos
|
39
|
+
Invalid syntax for include tag:
|
40
|
+
|
41
|
+
#{@params}
|
42
|
+
|
43
|
+
Valid syntax:
|
44
|
+
|
45
|
+
{% include file.ext param='value' param2="value" %}
|
46
|
+
|
47
|
+
eos
|
48
|
+
end
|
7
49
|
end
|
8
50
|
|
9
51
|
def render(context)
|
@@ -22,7 +64,9 @@ module Jekyll
|
|
22
64
|
if choices.include?(@file)
|
23
65
|
source = File.read(@file)
|
24
66
|
partial = Liquid::Template.parse(source)
|
67
|
+
|
25
68
|
context.stack do
|
69
|
+
context['include'] = parse_params(context) if @params
|
26
70
|
partial.render(context)
|
27
71
|
end
|
28
72
|
else
|
data/site/_config.yml
CHANGED
@@ -5,6 +5,9 @@
|
|
5
5
|
<li class="{% if page.title == "Welcome" %}current{% endif %}">
|
6
6
|
<a href="{{ site.url }}/docs/home">Welcome</a>
|
7
7
|
</li>
|
8
|
+
<li class="{% if page.title == "Quick-start guide" %}current{% endif %}">
|
9
|
+
<a href="{{ site.url }}/docs/quickstart">Quick-start guide</a>
|
10
|
+
</li>
|
8
11
|
<li class="{% if page.title == "Installation" %}current{% endif %}">
|
9
12
|
<a href="{{ site.url }}/docs/installation">Installation</a>
|
10
13
|
</li>
|
@@ -26,6 +29,9 @@
|
|
26
29
|
<li class="{% if page.title == "Writing posts" %}current{% endif %}">
|
27
30
|
<a href="{{ site.url }}/docs/posts">Writing posts</a>
|
28
31
|
</li>
|
32
|
+
<li class="{% if page.title == "Working with drafts" %}current{% endif %}">
|
33
|
+
<a href="{{ site.url }}/docs/drafts">Working with drafts</a>
|
34
|
+
</li>
|
29
35
|
<li class="{% if page.title == "Creating pages" %}current{% endif %}">
|
30
36
|
<a href="{{ site.url }}/docs/pages">Creating pages</a>
|
31
37
|
</li>
|
@@ -65,9 +71,6 @@
|
|
65
71
|
</ul>
|
66
72
|
<h4>Miscellaneous</h4>
|
67
73
|
<ul>
|
68
|
-
<li class="{% if page.title == "Contributing" %}current{% endif %}">
|
69
|
-
<a href="{{ site.url }}/docs/contributing">Contributing</a>
|
70
|
-
</li>
|
71
74
|
<li class="{% if page.title == "Troubleshooting" %}current{% endif %}">
|
72
75
|
<a href="{{ site.url }}/docs/troubleshooting">Troubleshooting</a>
|
73
76
|
</li>
|
@@ -80,6 +83,12 @@
|
|
80
83
|
<li class="{% if page.title == "Upgrading" %}current{% endif %}">
|
81
84
|
<a href="{{ site.url }}/docs/upgrading">Upgrading</a>
|
82
85
|
</li>
|
86
|
+
</ul>
|
87
|
+
<h4>Meta</h4>
|
88
|
+
<ul>
|
89
|
+
<li class="{% if page.title == "Contributing" %}current{% endif %}">
|
90
|
+
<a href="{{ site.url }}/docs/contributing">Contributing</a>
|
91
|
+
</li>
|
83
92
|
<li class="{% if page.title == "History" %}current{% endif %}">
|
84
93
|
<a href="{{ site.url }}/docs/history">History</a>
|
85
94
|
</li>
|