jekyll 0.10.0 → 0.11.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.
- data/Gemfile +2 -0
- data/History.txt +20 -1
- data/README.textile +1 -1
- data/Rakefile +2 -0
- data/bin/jekyll +92 -2
- data/doc/output/book.html +574 -0
- data/doc/output/ch00-preface.asc +41 -0
- data/doc/output/ch01-quick-start.asc +153 -0
- data/doc/output/ch02-directory-layout.asc +90 -0
- data/doc/output/stylesheets/handbookish-quirks.css +0 -0
- data/doc/output/stylesheets/handbookish.css +231 -0
- data/doc/output/stylesheets/scribe-quirks.css +0 -0
- data/doc/output/stylesheets/scribe.css +177 -0
- data/features/post_data.feature +2 -2
- data/features/site_configuration.feature +7 -0
- data/features/support/env.rb +3 -0
- data/g.pl +48 -0
- data/jekyll.gemspec +35 -16
- data/lib/jekyll.rb +11 -4
- data/lib/jekyll/converters/markdown.rb +14 -2
- data/lib/jekyll/converters/textile.rb +2 -1
- data/lib/jekyll/convertible.rb +34 -19
- data/lib/jekyll/filters.rb +66 -1
- data/lib/jekyll/generators/pagination.rb +33 -7
- data/lib/jekyll/layout.rb +18 -10
- data/lib/jekyll/migrators/csv.rb +3 -3
- data/lib/jekyll/migrators/drupal.rb +12 -6
- data/lib/jekyll/migrators/enki.rb +49 -0
- data/lib/jekyll/migrators/marley.rb +0 -1
- data/lib/jekyll/migrators/mephisto.rb +17 -12
- data/lib/jekyll/migrators/mt.rb +26 -17
- data/lib/jekyll/migrators/posterous.rb +68 -0
- data/lib/jekyll/migrators/textpattern.rb +15 -8
- data/lib/jekyll/migrators/tumblr.rb +119 -0
- data/lib/jekyll/migrators/typo.rb +8 -6
- data/lib/jekyll/migrators/wordpress.rb +23 -16
- data/lib/jekyll/migrators/wordpressdotcom.rb +70 -0
- data/lib/jekyll/page.rb +56 -35
- data/lib/jekyll/plugin.rb +1 -0
- data/lib/jekyll/post.rb +25 -14
- data/lib/jekyll/site.rb +138 -80
- data/lib/jekyll/static_file.rb +12 -15
- data/lib/jekyll/tags/highlight.rb +5 -5
- data/output/stylesheets/scribe-quirks.css +0 -0
- data/output/stylesheets/scribe.css +177 -0
- data/test/helper.rb +3 -3
- data/test/source/_posts/2011-04-12-md-extension.md +7 -0
- data/test/source/_posts/2011-04-12-text-extension.text +0 -0
- data/test/suite.rb +3 -1
- data/test/test_configuration.rb +1 -1
- data/test/test_core_ext.rb +1 -1
- data/test/test_filters.rb +10 -1
- data/test/test_generated_site.rb +2 -2
- data/test/test_kramdown.rb +1 -1
- data/test/test_page.rb +1 -1
- data/test/test_pager.rb +1 -1
- data/test/test_post.rb +49 -2
- data/test/test_rdiscount.rb +1 -1
- data/test/test_redcarpet.rb +21 -0
- data/test/test_site.rb +1 -1
- data/test/test_tags.rb +14 -1
- metadata +104 -38
- data/lib/jekyll/albino.rb +0 -120
- data/lib/jekyll/migrators/wordpress.com.rb +0 -38
data/lib/jekyll/convertible.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
# Convertible provides methods for converting a pagelike item
|
2
4
|
# from a certain type of markup into actual content
|
3
5
|
#
|
@@ -10,26 +12,27 @@
|
|
10
12
|
# self.output=
|
11
13
|
module Jekyll
|
12
14
|
module Convertible
|
13
|
-
#
|
15
|
+
# Returns the contents as a String.
|
14
16
|
def to_s
|
15
17
|
self.content || ''
|
16
18
|
end
|
17
19
|
|
18
|
-
# Read the YAML frontmatter
|
19
|
-
#
|
20
|
-
#
|
20
|
+
# Read the YAML frontmatter.
|
21
|
+
#
|
22
|
+
# base - The String path to the dir containing the file.
|
23
|
+
# name - The String filename of the file.
|
21
24
|
#
|
22
|
-
# Returns nothing
|
25
|
+
# Returns nothing.
|
23
26
|
def read_yaml(base, name)
|
24
27
|
self.content = File.read(File.join(base, name))
|
25
28
|
|
26
29
|
if self.content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
|
27
|
-
self.content =
|
30
|
+
self.content = $POSTMATCH
|
28
31
|
|
29
32
|
begin
|
30
33
|
self.data = YAML.load($1)
|
31
34
|
rescue => e
|
32
|
-
puts "YAML Exception: #{e.message}"
|
35
|
+
puts "YAML Exception reading #{name}: #{e.message}"
|
33
36
|
end
|
34
37
|
end
|
35
38
|
|
@@ -38,42 +41,46 @@ module Jekyll
|
|
38
41
|
|
39
42
|
# Transform the contents based on the content type.
|
40
43
|
#
|
41
|
-
# Returns nothing
|
44
|
+
# Returns nothing.
|
42
45
|
def transform
|
43
46
|
self.content = converter.convert(self.content)
|
44
47
|
end
|
45
48
|
|
46
|
-
# Determine the extension depending on content_type
|
49
|
+
# Determine the extension depending on content_type.
|
47
50
|
#
|
48
|
-
# Returns the
|
51
|
+
# Returns the String extension for the output file.
|
52
|
+
# e.g. ".html" for an HTML output file.
|
49
53
|
def output_ext
|
50
54
|
converter.output_ext(self.ext)
|
51
55
|
end
|
52
56
|
|
53
57
|
# Determine which converter to use based on this convertible's
|
54
|
-
# extension
|
58
|
+
# extension.
|
59
|
+
#
|
60
|
+
# Returns the Converter instance.
|
55
61
|
def converter
|
56
62
|
@converter ||= self.site.converters.find { |c| c.matches(self.ext) }
|
57
63
|
end
|
58
64
|
|
59
|
-
# Add any necessary layouts to this convertible document
|
60
|
-
#
|
61
|
-
#
|
65
|
+
# Add any necessary layouts to this convertible document.
|
66
|
+
#
|
67
|
+
# payload - The site payload Hash.
|
68
|
+
# layouts - A Hash of {"name" => "layout"}.
|
62
69
|
#
|
63
|
-
# Returns nothing
|
70
|
+
# Returns nothing.
|
64
71
|
def do_layout(payload, layouts)
|
65
72
|
info = { :filters => [Jekyll::Filters], :registers => { :site => self.site } }
|
66
73
|
|
67
74
|
# render and transform content (this becomes the final content of the object)
|
68
75
|
payload["pygments_prefix"] = converter.pygments_prefix
|
69
76
|
payload["pygments_suffix"] = converter.pygments_suffix
|
70
|
-
|
77
|
+
|
71
78
|
begin
|
72
79
|
self.content = Liquid::Template.parse(self.content).render(payload, info)
|
73
80
|
rescue => e
|
74
|
-
puts "Liquid Exception: #{e.message} in #{self.
|
81
|
+
puts "Liquid Exception: #{e.message} in #{self.name}"
|
75
82
|
end
|
76
|
-
|
83
|
+
|
77
84
|
self.transform
|
78
85
|
|
79
86
|
# output keeps track of what will finally be written
|
@@ -81,6 +88,8 @@ module Jekyll
|
|
81
88
|
|
82
89
|
# recursively render layouts
|
83
90
|
layout = layouts[self.data["layout"]]
|
91
|
+
used = Set.new([layout])
|
92
|
+
|
84
93
|
while layout
|
85
94
|
payload = payload.deep_merge({"content" => self.output, "page" => layout.data})
|
86
95
|
|
@@ -90,7 +99,13 @@ module Jekyll
|
|
90
99
|
puts "Liquid Exception: #{e.message} in #{self.data["layout"]}"
|
91
100
|
end
|
92
101
|
|
93
|
-
layout = layouts[layout.data["layout"]]
|
102
|
+
if layout = layouts[layout.data["layout"]]
|
103
|
+
if used.include?(layout)
|
104
|
+
layout = nil # avoid recursive chain
|
105
|
+
else
|
106
|
+
used << layout
|
107
|
+
end
|
108
|
+
end
|
94
109
|
end
|
95
110
|
end
|
96
111
|
end
|
data/lib/jekyll/filters.rb
CHANGED
@@ -3,18 +3,56 @@ require 'uri'
|
|
3
3
|
module Jekyll
|
4
4
|
|
5
5
|
module Filters
|
6
|
+
# Convert a Textile string into HTML output.
|
7
|
+
#
|
8
|
+
# input - The Textile String to convert.
|
9
|
+
#
|
10
|
+
# Returns the HTML formatted String.
|
6
11
|
def textilize(input)
|
7
|
-
|
12
|
+
site = @context.registers[:site]
|
13
|
+
converter = site.getConverterImpl(Jekyll::TextileConverter)
|
14
|
+
converter.convert(input)
|
8
15
|
end
|
9
16
|
|
17
|
+
# Convert a Markdown string into HTML output.
|
18
|
+
#
|
19
|
+
# input - The Markdown String to convert.
|
20
|
+
#
|
21
|
+
# Returns the HTML formatted String.
|
22
|
+
def markdownify(input)
|
23
|
+
site = @context.registers[:site]
|
24
|
+
converter = site.getConverterImpl(Jekyll::MarkdownConverter)
|
25
|
+
converter.convert(input)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Format a date in short format e.g. "27 Jan 2011".
|
29
|
+
#
|
30
|
+
# date - the Time to format.
|
31
|
+
#
|
32
|
+
# Returns the formatting String.
|
10
33
|
def date_to_string(date)
|
11
34
|
date.strftime("%d %b %Y")
|
12
35
|
end
|
13
36
|
|
37
|
+
# Format a date in long format e.g. "27 January 2011".
|
38
|
+
#
|
39
|
+
# date - The Time to format.
|
40
|
+
#
|
41
|
+
# Returns the formatted String.
|
14
42
|
def date_to_long_string(date)
|
15
43
|
date.strftime("%d %B %Y")
|
16
44
|
end
|
17
45
|
|
46
|
+
# Format a date for use in XML.
|
47
|
+
#
|
48
|
+
# date - The Time to format.
|
49
|
+
#
|
50
|
+
# Examples
|
51
|
+
#
|
52
|
+
# date_to_xmlschema(Time.now)
|
53
|
+
# # => "2011-04-24T20:34:46+08:00"
|
54
|
+
#
|
55
|
+
# Returns the formatted String.
|
18
56
|
def date_to_xmlschema(date)
|
19
57
|
date.xmlschema
|
20
58
|
end
|
@@ -23,6 +61,17 @@ module Jekyll
|
|
23
61
|
CGI.escapeHTML(input)
|
24
62
|
end
|
25
63
|
|
64
|
+
# CGI escape a string for use in a URL. Replaces any special characters
|
65
|
+
# with appropriate %XX replacements.
|
66
|
+
#
|
67
|
+
# input - The String to escape.
|
68
|
+
#
|
69
|
+
# Examples
|
70
|
+
#
|
71
|
+
# cgi_escape('foo,bar;baz?')
|
72
|
+
# # => "foo%2Cbar%3Bbaz%3F"
|
73
|
+
#
|
74
|
+
# Returns the escaped String.
|
26
75
|
def cgi_escape(input)
|
27
76
|
CGI::escape(input)
|
28
77
|
end
|
@@ -31,10 +80,26 @@ module Jekyll
|
|
31
80
|
URI.escape(input)
|
32
81
|
end
|
33
82
|
|
83
|
+
# Count the number of words in the input string.
|
84
|
+
#
|
85
|
+
# input - The String on which to operate.
|
86
|
+
#
|
87
|
+
# Returns the Integer word count.
|
34
88
|
def number_of_words(input)
|
35
89
|
input.split.length
|
36
90
|
end
|
37
91
|
|
92
|
+
# Join an array of things into a string by separating with commes and the
|
93
|
+
# word "and" for the last one.
|
94
|
+
#
|
95
|
+
# array - The Array of Strings to join.
|
96
|
+
#
|
97
|
+
# Examples
|
98
|
+
#
|
99
|
+
# array_to_sentence_string(["apples", "oranges", "grapes"])
|
100
|
+
# # => "apples, oranges, and grapes"
|
101
|
+
#
|
102
|
+
# Returns the formatted String.
|
38
103
|
def array_to_sentence_string(array)
|
39
104
|
connector = "and"
|
40
105
|
case array.length
|
@@ -1,8 +1,14 @@
|
|
1
1
|
module Jekyll
|
2
2
|
|
3
3
|
class Pagination < Generator
|
4
|
+
# This generator is safe from arbitrary code execution.
|
4
5
|
safe true
|
5
6
|
|
7
|
+
# Generate paginated pages if necessary.
|
8
|
+
#
|
9
|
+
# site - The Site.
|
10
|
+
#
|
11
|
+
# Returns nothing.
|
6
12
|
def generate(site)
|
7
13
|
site.pages.dup.each do |page|
|
8
14
|
paginate(site, page) if Pager.pagination_enabled?(site.config, page.name)
|
@@ -10,9 +16,11 @@ module Jekyll
|
|
10
16
|
end
|
11
17
|
|
12
18
|
# Paginates the blog's posts. Renders the index.html file into paginated
|
13
|
-
# directories,
|
19
|
+
# directories, e.g.: page2/index.html, page3/index.html, etc and adds more
|
14
20
|
# site-wide data.
|
15
|
-
#
|
21
|
+
#
|
22
|
+
# site - The Site.
|
23
|
+
# page - The index.html Page that requires pagination.
|
16
24
|
#
|
17
25
|
# {"paginator" => { "page" => <Number>,
|
18
26
|
# "per_page" => <Number>,
|
@@ -36,22 +44,38 @@ module Jekyll
|
|
36
44
|
end
|
37
45
|
end
|
38
46
|
end
|
39
|
-
|
40
47
|
end
|
41
48
|
|
42
49
|
class Pager
|
43
50
|
attr_reader :page, :per_page, :posts, :total_posts, :total_pages, :previous_page, :next_page
|
44
51
|
|
52
|
+
# Calculate the number of pages.
|
53
|
+
#
|
54
|
+
# all_posts - The Array of all Posts.
|
55
|
+
# per_page - The Integer of entries per page.
|
56
|
+
#
|
57
|
+
# Returns the Integer number of pages.
|
45
58
|
def self.calculate_pages(all_posts, per_page)
|
46
|
-
|
47
|
-
num_pages = num_pages + 1 if all_posts.size % per_page.to_i != 0
|
48
|
-
num_pages
|
59
|
+
(all_posts.size.to_f / per_page.to_i).ceil
|
49
60
|
end
|
50
61
|
|
62
|
+
# Determine if pagination is enabled for a given file.
|
63
|
+
#
|
64
|
+
# config - The configuration Hash.
|
65
|
+
# file - The String filename of the file.
|
66
|
+
#
|
67
|
+
# Returns true if pagination is enabled, false otherwise.
|
51
68
|
def self.pagination_enabled?(config, file)
|
52
69
|
file == 'index.html' && !config['paginate'].nil?
|
53
70
|
end
|
54
71
|
|
72
|
+
# Initialize a new Pager.
|
73
|
+
#
|
74
|
+
# config - The Hash configuration of the site.
|
75
|
+
# page - The Integer page number.
|
76
|
+
# all_posts - The Array of all the site's Posts.
|
77
|
+
# num_pages - The Integer number of pages or nil if you'd like the number
|
78
|
+
# of pages calculated.
|
55
79
|
def initialize(config, page, all_posts, num_pages = nil)
|
56
80
|
@page = page
|
57
81
|
@per_page = config['paginate'].to_i
|
@@ -70,6 +94,9 @@ module Jekyll
|
|
70
94
|
@next_page = @page != @total_pages ? @page + 1 : nil
|
71
95
|
end
|
72
96
|
|
97
|
+
# Convert this Pager's data to a Hash suitable for use by Liquid.
|
98
|
+
#
|
99
|
+
# Returns the Hash representation of this Pager.
|
73
100
|
def to_liquid
|
74
101
|
{
|
75
102
|
'page' => page,
|
@@ -83,5 +110,4 @@ module Jekyll
|
|
83
110
|
end
|
84
111
|
end
|
85
112
|
|
86
|
-
|
87
113
|
end
|
data/lib/jekyll/layout.rb
CHANGED
@@ -3,16 +3,23 @@ module Jekyll
|
|
3
3
|
class Layout
|
4
4
|
include Convertible
|
5
5
|
|
6
|
-
|
6
|
+
# Gets the Site object.
|
7
|
+
attr_reader :site
|
8
|
+
|
9
|
+
# Gets/Sets the extension of this layout.
|
7
10
|
attr_accessor :ext
|
8
|
-
|
11
|
+
|
12
|
+
# Gets/Sets the Hash that holds the metadata for this layout.
|
13
|
+
attr_accessor :data
|
14
|
+
|
15
|
+
# Gets/Sets the content of this layout.
|
16
|
+
attr_accessor :content
|
9
17
|
|
10
18
|
# Initialize a new Layout.
|
11
|
-
# +site+ is the Site
|
12
|
-
# +base+ is the String path to the <source>
|
13
|
-
# +name+ is the String filename of the post file
|
14
19
|
#
|
15
|
-
#
|
20
|
+
# site - The Site.
|
21
|
+
# base - The String path to the source.
|
22
|
+
# name - The String filename of the post file.
|
16
23
|
def initialize(site, base, name)
|
17
24
|
@site = site
|
18
25
|
@base = base
|
@@ -24,13 +31,14 @@ module Jekyll
|
|
24
31
|
self.read_yaml(base, name)
|
25
32
|
end
|
26
33
|
|
27
|
-
# Extract information from the layout filename
|
28
|
-
#
|
34
|
+
# Extract information from the layout filename.
|
35
|
+
#
|
36
|
+
# name - The String filename of the layout file.
|
29
37
|
#
|
30
|
-
# Returns nothing
|
38
|
+
# Returns nothing.
|
31
39
|
def process(name)
|
32
40
|
self.ext = File.extname(name)
|
33
41
|
end
|
34
42
|
end
|
35
43
|
|
36
|
-
end
|
44
|
+
end
|
data/lib/jekyll/migrators/csv.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Jekyll
|
2
2
|
module CSV
|
3
|
-
#Reads a csv with title, permalink, body, published_at, and filter.
|
4
|
-
#It creates a post file for each row in the csv
|
3
|
+
# Reads a csv with title, permalink, body, published_at, and filter.
|
4
|
+
# It creates a post file for each row in the csv
|
5
5
|
def self.process(file = "posts.csv")
|
6
6
|
FileUtils.mkdir_p "_posts"
|
7
7
|
posts = 0
|
@@ -23,4 +23,4 @@ title: #{row[0]}
|
|
23
23
|
"Created #{posts} posts!"
|
24
24
|
end
|
25
25
|
end
|
26
|
-
end
|
26
|
+
end
|
@@ -11,12 +11,18 @@ require 'yaml'
|
|
11
11
|
|
12
12
|
module Jekyll
|
13
13
|
module Drupal
|
14
|
-
|
15
|
-
#
|
16
|
-
#
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
# Reads a MySQL database via Sequel and creates a post file for each post
|
15
|
+
# in wp_posts that has post_status = 'publish'. This restriction is made
|
16
|
+
# because 'draft' posts are not guaranteed to have valid dates.
|
17
|
+
QUERY = "SELECT node.nid, \
|
18
|
+
node.title, \
|
19
|
+
node_revisions.body, \
|
20
|
+
node.created, \
|
21
|
+
node.status \
|
22
|
+
FROM node, \
|
23
|
+
node_revisions \
|
24
|
+
WHERE (node.type = 'blog' OR node.type = 'story') \
|
25
|
+
AND node.vid = node_revisions.vid"
|
20
26
|
|
21
27
|
def self.process(dbname, user, pass, host = 'localhost')
|
22
28
|
db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host, :encoding => 'utf8')
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Adapted by Rodrigo Pinto <rodrigopqn@gmail.com>
|
2
|
+
# Based on typo.rb by Toby DiPasquale
|
3
|
+
|
4
|
+
require 'fileutils'
|
5
|
+
require 'rubygems'
|
6
|
+
require 'sequel'
|
7
|
+
|
8
|
+
module Jekyll
|
9
|
+
module Enki
|
10
|
+
SQL = <<-EOS
|
11
|
+
SELECT p.id,
|
12
|
+
p.title,
|
13
|
+
p.slug,
|
14
|
+
p.body,
|
15
|
+
p.published_at as date,
|
16
|
+
p.cached_tag_list as tags
|
17
|
+
FROM posts p
|
18
|
+
EOS
|
19
|
+
|
20
|
+
# Just working with postgres, but can be easily adapted
|
21
|
+
# to work with both mysql and postgres.
|
22
|
+
def self.process(dbname, user, pass, host = 'localhost')
|
23
|
+
FileUtils.mkdir_p('_posts')
|
24
|
+
db = Sequel.postgres(:database => dbname,
|
25
|
+
:user => user,
|
26
|
+
:password => pass,
|
27
|
+
:host => host,
|
28
|
+
:encoding => 'utf8')
|
29
|
+
|
30
|
+
db[SQL].each do |post|
|
31
|
+
name = [ sprintf("%.04d", post[:date].year),
|
32
|
+
sprintf("%.02d", post[:date].month),
|
33
|
+
sprintf("%.02d", post[:date].day),
|
34
|
+
post[:slug].strip ].join('-')
|
35
|
+
name += '.textile'
|
36
|
+
|
37
|
+
File.open("_posts/#{name}", 'w') do |f|
|
38
|
+
f.puts({ 'layout' => 'post',
|
39
|
+
'title' => post[:title].to_s,
|
40
|
+
'enki_id' => post[:id],
|
41
|
+
'categories' => post[:tags]
|
42
|
+
}.delete_if { |k, v| v.nil? || v == '' }.to_yaml)
|
43
|
+
f.puts '---'
|
44
|
+
f.puts post[:body].delete("\r")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|