jekyll 0.4.1 → 0.5.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.
- data/History.txt +31 -1
- data/README.textile +23 -457
- data/Rakefile +91 -0
- data/VERSION.yml +2 -2
- data/bin/jekyll +61 -57
- data/lib/jekyll.rb +48 -32
- data/lib/jekyll/albino.rb +13 -7
- data/lib/jekyll/converters/mephisto.rb +8 -8
- data/lib/jekyll/converters/mt.rb +8 -8
- data/lib/jekyll/converters/textpattern.rb +4 -4
- data/lib/jekyll/converters/typo.rb +8 -8
- data/lib/jekyll/converters/wordpress.rb +1 -2
- data/lib/jekyll/convertible.rb +33 -22
- data/lib/jekyll/core_ext.rb +5 -5
- data/lib/jekyll/filters.rb +15 -7
- data/lib/jekyll/layout.rb +9 -6
- data/lib/jekyll/page.rb +13 -10
- data/lib/jekyll/post.rb +108 -39
- data/lib/jekyll/site.rb +121 -51
- data/lib/jekyll/tags/highlight.rb +12 -9
- data/lib/jekyll/tags/include.rb +5 -5
- data/test/helper.rb +20 -6
- data/test/source/_posts/2008-02-02-not-published.textile +8 -0
- data/test/source/_posts/2008-02-02-published.textile +8 -0
- data/test/source/_posts/2009-01-27-array-categories.textile +10 -0
- data/test/source/_posts/2009-01-27-categories.textile +7 -0
- data/test/source/_posts/2009-01-27-category.textile +7 -0
- data/test/source/_posts/2009-03-12-hash-#1.markdown +6 -0
- data/test/test_filters.rb +39 -27
- data/test/test_generated_site.rb +32 -16
- data/test/test_post.rb +258 -102
- data/test/test_site.rb +60 -28
- data/test/test_tags.rb +103 -18
- metadata +25 -70
- data/test/dest/2008/10/18/foo-bar.html +0 -28
- data/test/dest/2008/11/21/complex.html +0 -29
- data/test/dest/2008/12/13/include.html +0 -30
- data/test/dest/_posts/2008-10-18-foo-bar.html +0 -28
- data/test/dest/_posts/2008-11-21-complex.html +0 -29
- data/test/dest/_posts/2008-12-03-permalinked-post.html +0 -2
- data/test/dest/_posts/2008-12-13-include.html +0 -30
- data/test/dest/category/2008/09/23/categories.html +0 -27
- data/test/dest/category/_posts/2008-9-23-categories.html +0 -27
- data/test/dest/css/screen.css +0 -76
- data/test/dest/foo/2008/12/12/topical-post.html +0 -28
- data/test/dest/foo/_posts/bar/2008-12-12-topical-post.html +0 -28
- data/test/dest/index.html +0 -60
- data/test/dest/my_category/permalinked-post +0 -2
- data/test/dest/z_category/2008/09/23/categories.html +0 -27
- data/test/dest/z_category/_posts/2008-9-23-categories.html +0 -27
- data/test/test_jekyll.rb +0 -0
data/lib/jekyll/converters/mt.rb
CHANGED
@@ -11,31 +11,31 @@ require 'fileutils'
|
|
11
11
|
# installed, running the following commands should work:
|
12
12
|
# $ sudo gem install sequel
|
13
13
|
# $ sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
|
14
|
-
|
14
|
+
|
15
15
|
module Jekyll
|
16
16
|
module MT
|
17
17
|
# This query will pull blog posts from all entries across all blogs. If
|
18
18
|
# you've got unpublished, deleted or otherwise hidden posts please sift
|
19
19
|
# through the created posts to make sure nothing is accidently published.
|
20
20
|
QUERY = "SELECT entry_id, entry_basename, entry_text, entry_text_more, entry_created_on, entry_title FROM mt_entry"
|
21
|
-
|
21
|
+
|
22
22
|
def self.process(dbname, user, pass, host = 'localhost')
|
23
23
|
db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host)
|
24
|
-
|
24
|
+
|
25
25
|
FileUtils.mkdir_p "_posts"
|
26
|
-
|
26
|
+
|
27
27
|
db[QUERY].each do |post|
|
28
28
|
title = post[:entry_title]
|
29
29
|
slug = post[:entry_basename]
|
30
30
|
date = post[:entry_created_on]
|
31
31
|
content = post[:entry_text]
|
32
32
|
more_content = post[:entry_text_more]
|
33
|
-
|
33
|
+
|
34
34
|
# Be sure to include the body and extended body.
|
35
35
|
if more_content != nil
|
36
36
|
content = content + " \n" + more_content
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# Ideally, this script would determine the post format (markdown, html
|
40
40
|
# , etc) and create files with proper extensions. At this point it
|
41
41
|
# just assumes that markdown will be acceptable.
|
@@ -46,14 +46,14 @@ module Jekyll
|
|
46
46
|
'title' => title.to_s,
|
47
47
|
'mt_id' => post[:entry_id],
|
48
48
|
}.delete_if { |k,v| v.nil? || v == ''}.to_yaml
|
49
|
-
|
49
|
+
|
50
50
|
File.open("_posts/#{name}", "w") do |f|
|
51
51
|
f.puts data
|
52
52
|
f.puts "---"
|
53
53
|
f.puts content
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
@@ -18,20 +18,20 @@ module Jekyll
|
|
18
18
|
|
19
19
|
def self.process(dbname, user, pass, host = 'localhost')
|
20
20
|
db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host)
|
21
|
-
|
21
|
+
|
22
22
|
FileUtils.mkdir_p "_posts"
|
23
|
-
|
23
|
+
|
24
24
|
db[QUERY].each do |post|
|
25
25
|
# Get required fields and construct Jekyll compatible name
|
26
26
|
title = post[:Title]
|
27
27
|
slug = post[:url_title]
|
28
28
|
date = post[:Posted]
|
29
29
|
content = post[:Body]
|
30
|
-
|
30
|
+
|
31
31
|
name = [date.strftime("%Y-%m-%d"), slug].join('-') + ".textile"
|
32
32
|
|
33
33
|
# Get the relevant fields as a hash, delete empty fields and convert
|
34
|
-
# to YAML for the header
|
34
|
+
# to YAML for the header
|
35
35
|
data = {
|
36
36
|
'layout' => 'post',
|
37
37
|
'title' => title.to_s,
|
@@ -2,22 +2,22 @@
|
|
2
2
|
require 'fileutils'
|
3
3
|
require 'rubygems'
|
4
4
|
require 'sequel'
|
5
|
-
|
5
|
+
|
6
6
|
module Jekyll
|
7
7
|
module Typo
|
8
|
-
# this SQL *should* work for both MySQL and PostgreSQL, but I haven't
|
8
|
+
# this SQL *should* work for both MySQL and PostgreSQL, but I haven't
|
9
9
|
# tested PostgreSQL yet (as of 2008-12-16)
|
10
10
|
SQL = <<-EOS
|
11
11
|
SELECT c.id id,
|
12
|
-
c.title title,
|
13
|
-
c.permalink slug,
|
12
|
+
c.title title,
|
13
|
+
c.permalink slug,
|
14
14
|
c.body body,
|
15
|
-
c.published_at date,
|
15
|
+
c.published_at date,
|
16
16
|
c.state state,
|
17
17
|
COALESCE(tf.name, 'html') filter
|
18
|
-
FROM contents c
|
18
|
+
FROM contents c
|
19
19
|
LEFT OUTER JOIN text_filters tf
|
20
|
-
ON c.text_filter_id = tf.id
|
20
|
+
ON c.text_filter_id = tf.id
|
21
21
|
EOS
|
22
22
|
|
23
23
|
def self.process dbname, user, pass, host='localhost'
|
@@ -30,7 +30,7 @@ module Jekyll
|
|
30
30
|
sprintf("%.02d", post[:date].month),
|
31
31
|
sprintf("%.02d", post[:date].day),
|
32
32
|
post[:slug].strip ].join('-')
|
33
|
-
# Can have more than one text filter in this field, but we just want
|
33
|
+
# Can have more than one text filter in this field, but we just want
|
34
34
|
# the first one for this
|
35
35
|
name += '.' + post[:filter].split(' ')[0]
|
36
36
|
|
@@ -15,7 +15,7 @@ module Jekyll
|
|
15
15
|
# post in wp_posts that has post_status = 'publish'.
|
16
16
|
# This restriction is made because 'draft' posts are not guaranteed to
|
17
17
|
# have valid dates.
|
18
|
-
QUERY = "select
|
18
|
+
QUERY = "select post_title, post_name, post_date, post_content, post_excerpt, ID, guid from wp_posts where post_status = 'publish' and post_type = 'post'"
|
19
19
|
|
20
20
|
def self.process(dbname, user, pass, host = 'localhost')
|
21
21
|
db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host)
|
@@ -28,7 +28,6 @@ module Jekyll
|
|
28
28
|
slug = post[:post_name]
|
29
29
|
date = post[:post_date]
|
30
30
|
content = post[:post_content]
|
31
|
-
|
32
31
|
name = "%02d-%02d-%02d-%s.markdown" % [date.year, date.month, date.day,
|
33
32
|
slug]
|
34
33
|
|
data/lib/jekyll/convertible.rb
CHANGED
@@ -1,10 +1,15 @@
|
|
1
|
+
# Convertible provides methods for converting a pagelike item
|
2
|
+
# from a certain type of markup into actual content
|
3
|
+
#
|
4
|
+
# Requires
|
5
|
+
# self.site -> Jekyll::Site
|
1
6
|
module Jekyll
|
2
7
|
module Convertible
|
3
8
|
# Return the contents as a string
|
4
9
|
def to_s
|
5
10
|
self.content || ''
|
6
11
|
end
|
7
|
-
|
12
|
+
|
8
13
|
# Read the YAML frontmatter
|
9
14
|
# +base+ is the String path to the dir containing the file
|
10
15
|
# +name+ is the String filename of the file
|
@@ -12,58 +17,64 @@ module Jekyll
|
|
12
17
|
# Returns nothing
|
13
18
|
def read_yaml(base, name)
|
14
19
|
self.content = File.read(File.join(base, name))
|
15
|
-
|
20
|
+
|
16
21
|
if self.content =~ /^(---\s*\n.*?)\n---\s*\n/m
|
17
22
|
self.content = self.content[($1.size + 5)..-1]
|
18
|
-
|
23
|
+
|
19
24
|
self.data = YAML.load($1)
|
20
25
|
end
|
21
26
|
end
|
22
|
-
|
27
|
+
|
23
28
|
# Transform the contents based on the file extension.
|
24
29
|
#
|
25
30
|
# Returns nothing
|
26
31
|
def transform
|
27
|
-
case
|
28
|
-
when
|
32
|
+
case self.content_type
|
33
|
+
when 'textile'
|
29
34
|
self.ext = ".html"
|
30
|
-
self.content =
|
31
|
-
when
|
35
|
+
self.content = self.site.textile(self.content)
|
36
|
+
when 'markdown'
|
32
37
|
self.ext = ".html"
|
33
|
-
self.content =
|
38
|
+
self.content = self.site.markdown(self.content)
|
34
39
|
end
|
35
40
|
end
|
36
|
-
|
37
|
-
|
41
|
+
|
42
|
+
# Determine which formatting engine to use based on this convertible's
|
43
|
+
# extension
|
44
|
+
#
|
45
|
+
# Returns one of :textile, :markdown or :unknown
|
46
|
+
def content_type
|
38
47
|
case self.ext[1..-1]
|
39
48
|
when /textile/i
|
40
|
-
return
|
49
|
+
return 'textile'
|
41
50
|
when /markdown/i, /mkdn/i, /md/i
|
42
|
-
return
|
43
|
-
end
|
44
|
-
return
|
51
|
+
return 'markdown'
|
52
|
+
end
|
53
|
+
return 'unknown'
|
45
54
|
end
|
46
|
-
|
55
|
+
|
47
56
|
# Add any necessary layouts to this convertible document
|
48
57
|
# +layouts+ is a Hash of {"name" => "layout"}
|
49
58
|
# +site_payload+ is the site payload hash
|
50
59
|
#
|
51
60
|
# Returns nothing
|
52
61
|
def do_layout(payload, layouts)
|
62
|
+
info = { :filters => [Jekyll::Filters], :registers => { :site => self.site } }
|
63
|
+
|
53
64
|
# render and transform content (this becomes the final content of the object)
|
54
|
-
|
55
|
-
self.content = Liquid::Template.parse(self.content).render(payload,
|
65
|
+
payload["content_type"] = self.content_type
|
66
|
+
self.content = Liquid::Template.parse(self.content).render(payload, info)
|
56
67
|
self.transform
|
57
|
-
|
68
|
+
|
58
69
|
# output keeps track of what will finally be written
|
59
70
|
self.output = self.content
|
60
|
-
|
71
|
+
|
61
72
|
# recursively render layouts
|
62
73
|
layout = layouts[self.data["layout"]]
|
63
74
|
while layout
|
64
75
|
payload = payload.deep_merge({"content" => self.output, "page" => layout.data})
|
65
|
-
self.output = Liquid::Template.parse(layout.content).render(payload,
|
66
|
-
|
76
|
+
self.output = Liquid::Template.parse(layout.content).render(payload, info)
|
77
|
+
|
67
78
|
layout = layouts[layout.data["layout"]]
|
68
79
|
end
|
69
80
|
end
|
data/lib/jekyll/core_ext.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
class Hash
|
2
2
|
# Merges self with another hash, recursively.
|
3
|
-
#
|
3
|
+
#
|
4
4
|
# This code was lovingly stolen from some random gem:
|
5
5
|
# http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# Thanks to whoever made it.
|
8
8
|
def deep_merge(hash)
|
9
9
|
target = dup
|
10
|
-
|
10
|
+
|
11
11
|
hash.keys.each do |key|
|
12
12
|
if hash[key].is_a? Hash and self[key].is_a? Hash
|
13
13
|
target[key] = target[key].deep_merge(hash[key])
|
14
14
|
next
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
target[key] = hash[key]
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
target
|
21
21
|
end
|
22
22
|
end
|
data/lib/jekyll/filters.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
module Jekyll
|
2
|
-
|
2
|
+
|
3
3
|
module Filters
|
4
|
+
def textilize(input)
|
5
|
+
RedCloth.new(input).to_html
|
6
|
+
end
|
7
|
+
|
4
8
|
def date_to_string(date)
|
5
9
|
date.strftime("%d %b %Y")
|
6
10
|
end
|
@@ -8,19 +12,23 @@ module Jekyll
|
|
8
12
|
def date_to_long_string(date)
|
9
13
|
date.strftime("%d %B %Y")
|
10
14
|
end
|
11
|
-
|
15
|
+
|
12
16
|
def date_to_xmlschema(date)
|
13
17
|
date.xmlschema
|
14
18
|
end
|
15
|
-
|
19
|
+
|
16
20
|
def xml_escape(input)
|
17
|
-
|
21
|
+
CGI.escapeHTML(input)
|
18
22
|
end
|
19
|
-
|
23
|
+
|
24
|
+
def cgi_escape(input)
|
25
|
+
CGI::escape(input)
|
26
|
+
end
|
27
|
+
|
20
28
|
def number_of_words(input)
|
21
29
|
input.split.length
|
22
30
|
end
|
23
|
-
|
31
|
+
|
24
32
|
def array_to_sentence_string(array)
|
25
33
|
connector = "and"
|
26
34
|
case array.length
|
@@ -35,5 +43,5 @@ module Jekyll
|
|
35
43
|
end
|
36
44
|
end
|
37
45
|
|
38
|
-
end
|
46
|
+
end
|
39
47
|
end
|
data/lib/jekyll/layout.rb
CHANGED
@@ -2,25 +2,28 @@ module Jekyll
|
|
2
2
|
|
3
3
|
class Layout
|
4
4
|
include Convertible
|
5
|
-
|
5
|
+
|
6
|
+
attr_accessor :site
|
6
7
|
attr_accessor :ext
|
7
8
|
attr_accessor :data, :content
|
8
|
-
|
9
|
+
|
9
10
|
# Initialize a new Layout.
|
11
|
+
# +site+ is the Site
|
10
12
|
# +base+ is the String path to the <source>
|
11
13
|
# +name+ is the String filename of the post file
|
12
14
|
#
|
13
15
|
# Returns <Page>
|
14
|
-
def initialize(base, name)
|
16
|
+
def initialize(site, base, name)
|
17
|
+
@site = site
|
15
18
|
@base = base
|
16
19
|
@name = name
|
17
|
-
|
20
|
+
|
18
21
|
self.data = {}
|
19
|
-
|
22
|
+
|
20
23
|
self.process(name)
|
21
24
|
self.read_yaml(base, name)
|
22
25
|
end
|
23
|
-
|
26
|
+
|
24
27
|
# Extract information from the layout filename
|
25
28
|
# +name+ is the String filename of the layout file
|
26
29
|
#
|
data/lib/jekyll/page.rb
CHANGED
@@ -2,28 +2,31 @@ module Jekyll
|
|
2
2
|
|
3
3
|
class Page
|
4
4
|
include Convertible
|
5
|
-
|
5
|
+
|
6
|
+
attr_accessor :site
|
6
7
|
attr_accessor :ext
|
7
8
|
attr_accessor :data, :content, :output
|
8
|
-
|
9
|
+
|
9
10
|
# Initialize a new Page.
|
11
|
+
# +site+ is the Site
|
10
12
|
# +base+ is the String path to the <source>
|
11
13
|
# +dir+ is the String path between <source> and the file
|
12
14
|
# +name+ is the String filename of the file
|
13
15
|
#
|
14
16
|
# Returns <Page>
|
15
|
-
def initialize(base, dir, name)
|
17
|
+
def initialize(site, base, dir, name)
|
18
|
+
@site = site
|
16
19
|
@base = base
|
17
20
|
@dir = dir
|
18
21
|
@name = name
|
19
|
-
|
22
|
+
|
20
23
|
self.data = {}
|
21
|
-
|
24
|
+
|
22
25
|
self.process(name)
|
23
26
|
self.read_yaml(File.join(base, dir), name)
|
24
27
|
#self.transform
|
25
28
|
end
|
26
|
-
|
29
|
+
|
27
30
|
# Extract information from the page filename
|
28
31
|
# +name+ is the String filename of the page file
|
29
32
|
#
|
@@ -31,7 +34,7 @@ module Jekyll
|
|
31
34
|
def process(name)
|
32
35
|
self.ext = File.extname(name)
|
33
36
|
end
|
34
|
-
|
37
|
+
|
35
38
|
# Add any necessary layouts to this post
|
36
39
|
# +layouts+ is a Hash of {"name" => "layout"}
|
37
40
|
# +site_payload+ is the site payload hash
|
@@ -41,19 +44,19 @@ module Jekyll
|
|
41
44
|
payload = {"page" => self.data}.deep_merge(site_payload)
|
42
45
|
do_layout(payload, layouts)
|
43
46
|
end
|
44
|
-
|
47
|
+
|
45
48
|
# Write the generated page file to the destination directory.
|
46
49
|
# +dest+ is the String path to the destination dir
|
47
50
|
#
|
48
51
|
# Returns nothing
|
49
52
|
def write(dest)
|
50
53
|
FileUtils.mkdir_p(File.join(dest, @dir))
|
51
|
-
|
54
|
+
|
52
55
|
name = @name
|
53
56
|
if self.ext != ""
|
54
57
|
name = @name.split(".")[0..-2].join('.') + self.ext
|
55
58
|
end
|
56
|
-
|
59
|
+
|
57
60
|
path = File.join(dest, @dir, name)
|
58
61
|
File.open(path, 'w') do |f|
|
59
62
|
f.write(self.output)
|
data/lib/jekyll/post.rb
CHANGED
@@ -3,13 +3,13 @@ module Jekyll
|
|
3
3
|
class Post
|
4
4
|
include Comparable
|
5
5
|
include Convertible
|
6
|
-
|
6
|
+
|
7
7
|
class << self
|
8
8
|
attr_accessor :lsi
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
|
12
|
-
|
12
|
+
|
13
13
|
# Post name validator. Post filenames must be like:
|
14
14
|
# 2008-11-05-my-awesome-post.textile
|
15
15
|
#
|
@@ -17,36 +17,62 @@ module Jekyll
|
|
17
17
|
def self.valid?(name)
|
18
18
|
name =~ MATCHER
|
19
19
|
end
|
20
|
-
|
21
|
-
attr_accessor :date, :slug, :ext, :
|
22
|
-
|
23
|
-
|
20
|
+
|
21
|
+
attr_accessor :site, :date, :slug, :ext, :topics, :published, :data, :content, :output
|
22
|
+
attr_writer :categories
|
23
|
+
|
24
|
+
def categories
|
25
|
+
@categories ||= []
|
26
|
+
end
|
27
|
+
|
24
28
|
# Initialize this Post instance.
|
29
|
+
# +site+ is the Site
|
25
30
|
# +base+ is the String path to the dir containing the post file
|
26
31
|
# +name+ is the String filename of the post file
|
27
32
|
# +categories+ is an Array of Strings for the categories for this post
|
28
33
|
#
|
29
34
|
# Returns <Post>
|
30
|
-
def initialize(source, dir, name)
|
35
|
+
def initialize(site, source, dir, name)
|
36
|
+
@site = site
|
31
37
|
@base = File.join(source, dir, '_posts')
|
32
38
|
@name = name
|
33
|
-
|
39
|
+
|
34
40
|
self.categories = dir.split('/').reject { |x| x.empty? }
|
35
|
-
|
41
|
+
|
36
42
|
parts = name.split('/')
|
37
43
|
self.topics = parts.size > 1 ? parts[0..-2] : []
|
38
|
-
|
44
|
+
|
39
45
|
self.process(name)
|
40
46
|
self.read_yaml(@base, name)
|
47
|
+
|
48
|
+
if self.data.has_key?('published') && self.data['published'] == false
|
49
|
+
self.published = false
|
50
|
+
else
|
51
|
+
self.published = true
|
52
|
+
end
|
53
|
+
|
54
|
+
if self.categories.empty?
|
55
|
+
if self.data.has_key?('category')
|
56
|
+
self.categories << self.data['category']
|
57
|
+
elsif self.data.has_key?('categories')
|
58
|
+
# Look for categories in the YAML-header, either specified as
|
59
|
+
# an array or a string.
|
60
|
+
if self.data['categories'].kind_of? String
|
61
|
+
self.categories = self.data['categories'].split
|
62
|
+
else
|
63
|
+
self.categories = self.data['categories']
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
41
67
|
end
|
42
|
-
|
68
|
+
|
43
69
|
# Spaceship is based on Post#date
|
44
70
|
#
|
45
71
|
# Returns -1, 0, 1
|
46
72
|
def <=>(other)
|
47
73
|
self.date <=> other.date
|
48
74
|
end
|
49
|
-
|
75
|
+
|
50
76
|
# Extract information from the post filename
|
51
77
|
# +name+ is the String filename of the post file
|
52
78
|
#
|
@@ -57,7 +83,7 @@ module Jekyll
|
|
57
83
|
self.slug = slug
|
58
84
|
self.ext = ext
|
59
85
|
end
|
60
|
-
|
86
|
+
|
61
87
|
# The generated directory into which the post will be placed
|
62
88
|
# upon generation. This is derived from the permalink or, if
|
63
89
|
# permalink is absent, set to the default date
|
@@ -65,18 +91,9 @@ module Jekyll
|
|
65
91
|
#
|
66
92
|
# Returns <String>
|
67
93
|
def dir
|
68
|
-
|
69
|
-
permalink.to_s.split("/")[0..-2].join("/") + '/'
|
70
|
-
else
|
71
|
-
prefix = self.categories.empty? ? '' : '/' + self.categories.join('/')
|
72
|
-
if Jekyll.permalink_style == :date
|
73
|
-
prefix + date.strftime("/%Y/%m/%d/")
|
74
|
-
else
|
75
|
-
prefix + '/'
|
76
|
-
end
|
77
|
-
end
|
94
|
+
File.dirname(url)
|
78
95
|
end
|
79
|
-
|
96
|
+
|
80
97
|
# The full path and filename of the post.
|
81
98
|
# Defined in the YAML of the post body
|
82
99
|
# (Optional)
|
@@ -85,30 +102,53 @@ module Jekyll
|
|
85
102
|
def permalink
|
86
103
|
self.data && self.data['permalink']
|
87
104
|
end
|
88
|
-
|
105
|
+
|
106
|
+
def template
|
107
|
+
case self.site.permalink_style
|
108
|
+
when :pretty
|
109
|
+
"/:categories/:year/:month/:day/:title"
|
110
|
+
when :none
|
111
|
+
"/:categories/:title.html"
|
112
|
+
when :date
|
113
|
+
"/:categories/:year/:month/:day/:title.html"
|
114
|
+
else
|
115
|
+
self.site.permalink_style.to_s
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
89
119
|
# The generated relative url of this post
|
90
120
|
# e.g. /2008/11/05/my-awesome-post.html
|
91
121
|
#
|
92
122
|
# Returns <String>
|
93
123
|
def url
|
94
|
-
permalink
|
124
|
+
return permalink if permalink
|
125
|
+
|
126
|
+
@url ||= {
|
127
|
+
"year" => date.strftime("%Y"),
|
128
|
+
"month" => date.strftime("%m"),
|
129
|
+
"day" => date.strftime("%d"),
|
130
|
+
"title" => CGI.escape(slug),
|
131
|
+
"categories" => categories.sort.join('/')
|
132
|
+
}.inject(template) { |result, token|
|
133
|
+
result.gsub(/:#{token.first}/, token.last)
|
134
|
+
}.gsub(/\/\//, "/")
|
95
135
|
end
|
96
|
-
|
136
|
+
|
97
137
|
# The UID for this post (useful in feeds)
|
98
138
|
# e.g. /2008/11/05/my-awesome-post
|
99
139
|
#
|
100
140
|
# Returns <String>
|
101
141
|
def id
|
102
|
-
self.dir
|
142
|
+
File.join(self.dir, self.slug)
|
103
143
|
end
|
104
|
-
|
144
|
+
|
105
145
|
# Calculate related posts.
|
106
146
|
#
|
107
147
|
# Returns [<Post>]
|
108
148
|
def related_posts(posts)
|
109
149
|
return [] unless posts.size > 1
|
110
|
-
|
111
|
-
if
|
150
|
+
|
151
|
+
if self.site.lsi
|
112
152
|
self.class.lsi ||= begin
|
113
153
|
puts "Running the classifier... this could take a while."
|
114
154
|
lsi = Classifier::LSI.new
|
@@ -123,7 +163,7 @@ module Jekyll
|
|
123
163
|
(posts - [self])[0..9]
|
124
164
|
end
|
125
165
|
end
|
126
|
-
|
166
|
+
|
127
167
|
# Add any necessary layouts to this post
|
128
168
|
# +layouts+ is a Hash of {"name" => "layout"}
|
129
169
|
# +site_payload+ is the site payload hash
|
@@ -137,23 +177,30 @@ module Jekyll
|
|
137
177
|
"page" => self.to_liquid
|
138
178
|
}
|
139
179
|
payload = payload.deep_merge(site_payload)
|
140
|
-
|
180
|
+
|
141
181
|
do_layout(payload, layouts)
|
142
182
|
end
|
143
|
-
|
183
|
+
|
144
184
|
# Write the generated post file to the destination directory.
|
145
185
|
# +dest+ is the String path to the destination dir
|
146
186
|
#
|
147
187
|
# Returns nothing
|
148
188
|
def write(dest)
|
149
189
|
FileUtils.mkdir_p(File.join(dest, dir))
|
150
|
-
|
151
|
-
|
190
|
+
|
191
|
+
# The url needs to be unescaped in order to preserve the correct filename
|
192
|
+
path = File.join(dest, CGI.unescape(self.url))
|
193
|
+
|
194
|
+
if template[/\.html$/].nil?
|
195
|
+
FileUtils.mkdir_p(path)
|
196
|
+
path = File.join(path, "index.html")
|
197
|
+
end
|
198
|
+
|
152
199
|
File.open(path, 'w') do |f|
|
153
200
|
f.write(self.output)
|
154
201
|
end
|
155
202
|
end
|
156
|
-
|
203
|
+
|
157
204
|
# Convert this post into a Hash for use in Liquid templates.
|
158
205
|
#
|
159
206
|
# Returns <Hash>
|
@@ -163,12 +210,34 @@ module Jekyll
|
|
163
210
|
"date" => self.date,
|
164
211
|
"id" => self.id,
|
165
212
|
"topics" => self.topics,
|
213
|
+
"categories" => self.categories,
|
214
|
+
"next" => self.next,
|
215
|
+
"previous" => self.previous,
|
166
216
|
"content" => self.content }.deep_merge(self.data)
|
167
217
|
end
|
168
|
-
|
218
|
+
|
169
219
|
def inspect
|
170
220
|
"<Post: #{self.id}>"
|
171
221
|
end
|
222
|
+
|
223
|
+
def next
|
224
|
+
pos = self.site.posts.index(self)
|
225
|
+
|
226
|
+
if pos && pos < self.site.posts.length-1
|
227
|
+
self.site.posts[pos+1]
|
228
|
+
else
|
229
|
+
nil
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def previous
|
234
|
+
pos = self.site.posts.index(self)
|
235
|
+
if pos && pos > 0
|
236
|
+
self.site.posts[pos-1]
|
237
|
+
else
|
238
|
+
nil
|
239
|
+
end
|
240
|
+
end
|
172
241
|
end
|
173
242
|
|
174
243
|
end
|