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.

Files changed (64) hide show
  1. data/Gemfile +2 -0
  2. data/History.txt +20 -1
  3. data/README.textile +1 -1
  4. data/Rakefile +2 -0
  5. data/bin/jekyll +92 -2
  6. data/doc/output/book.html +574 -0
  7. data/doc/output/ch00-preface.asc +41 -0
  8. data/doc/output/ch01-quick-start.asc +153 -0
  9. data/doc/output/ch02-directory-layout.asc +90 -0
  10. data/doc/output/stylesheets/handbookish-quirks.css +0 -0
  11. data/doc/output/stylesheets/handbookish.css +231 -0
  12. data/doc/output/stylesheets/scribe-quirks.css +0 -0
  13. data/doc/output/stylesheets/scribe.css +177 -0
  14. data/features/post_data.feature +2 -2
  15. data/features/site_configuration.feature +7 -0
  16. data/features/support/env.rb +3 -0
  17. data/g.pl +48 -0
  18. data/jekyll.gemspec +35 -16
  19. data/lib/jekyll.rb +11 -4
  20. data/lib/jekyll/converters/markdown.rb +14 -2
  21. data/lib/jekyll/converters/textile.rb +2 -1
  22. data/lib/jekyll/convertible.rb +34 -19
  23. data/lib/jekyll/filters.rb +66 -1
  24. data/lib/jekyll/generators/pagination.rb +33 -7
  25. data/lib/jekyll/layout.rb +18 -10
  26. data/lib/jekyll/migrators/csv.rb +3 -3
  27. data/lib/jekyll/migrators/drupal.rb +12 -6
  28. data/lib/jekyll/migrators/enki.rb +49 -0
  29. data/lib/jekyll/migrators/marley.rb +0 -1
  30. data/lib/jekyll/migrators/mephisto.rb +17 -12
  31. data/lib/jekyll/migrators/mt.rb +26 -17
  32. data/lib/jekyll/migrators/posterous.rb +68 -0
  33. data/lib/jekyll/migrators/textpattern.rb +15 -8
  34. data/lib/jekyll/migrators/tumblr.rb +119 -0
  35. data/lib/jekyll/migrators/typo.rb +8 -6
  36. data/lib/jekyll/migrators/wordpress.rb +23 -16
  37. data/lib/jekyll/migrators/wordpressdotcom.rb +70 -0
  38. data/lib/jekyll/page.rb +56 -35
  39. data/lib/jekyll/plugin.rb +1 -0
  40. data/lib/jekyll/post.rb +25 -14
  41. data/lib/jekyll/site.rb +138 -80
  42. data/lib/jekyll/static_file.rb +12 -15
  43. data/lib/jekyll/tags/highlight.rb +5 -5
  44. data/output/stylesheets/scribe-quirks.css +0 -0
  45. data/output/stylesheets/scribe.css +177 -0
  46. data/test/helper.rb +3 -3
  47. data/test/source/_posts/2011-04-12-md-extension.md +7 -0
  48. data/test/source/_posts/2011-04-12-text-extension.text +0 -0
  49. data/test/suite.rb +3 -1
  50. data/test/test_configuration.rb +1 -1
  51. data/test/test_core_ext.rb +1 -1
  52. data/test/test_filters.rb +10 -1
  53. data/test/test_generated_site.rb +2 -2
  54. data/test/test_kramdown.rb +1 -1
  55. data/test/test_page.rb +1 -1
  56. data/test/test_pager.rb +1 -1
  57. data/test/test_post.rb +49 -2
  58. data/test/test_rdiscount.rb +1 -1
  59. data/test/test_redcarpet.rb +21 -0
  60. data/test/test_site.rb +1 -1
  61. data/test/test_tags.rb +14 -1
  62. metadata +104 -38
  63. data/lib/jekyll/albino.rb +0 -120
  64. data/lib/jekyll/migrators/wordpress.com.rb +0 -38
@@ -17,7 +17,8 @@ module Jekyll
17
17
  end
18
18
 
19
19
  def matches(ext)
20
- ext =~ /textile/i
20
+ rgx = '(' + @config['textile_ext'].gsub(',','|') +')'
21
+ ext =~ Regexp.new(rgx, Regexp::IGNORECASE)
21
22
  end
22
23
 
23
24
  def output_ext(ext)
@@ -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
- # Return the contents as a string
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
- # +base+ is the String path to the dir containing the file
20
- # +name+ is the String filename of the file
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 = self.content[($1.size + $2.size)..-1]
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 extensions for the output file
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
- # +layouts+ is a Hash of {"name" => "layout"}
61
- # +site_payload+ is the site payload hash
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.data["layout"]}"
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
@@ -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
- TextileConverter.new.convert(input)
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, ie: page2/index.html, page3/index.html, etc and adds more
19
+ # directories, e.g.: page2/index.html, page3/index.html, etc and adds more
14
20
  # site-wide data.
15
- # +page+ is the index.html Page that requires pagination
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
- num_pages = all_posts.size / per_page.to_i
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
- attr_accessor :site
6
+ # Gets the Site object.
7
+ attr_reader :site
8
+
9
+ # Gets/Sets the extension of this layout.
7
10
  attr_accessor :ext
8
- attr_accessor :data, :content
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
- # Returns <Page>
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
- # +name+ is the String filename of the layout file
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
@@ -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
- # Reads a MySQL database via Sequel and creates a post file for each
16
- # post in wp_posts that has post_status = 'publish'.
17
- # This restriction is made because 'draft' posts are not guaranteed to
18
- # have valid dates.
19
- QUERY = "SELECT node.nid, node.title, node_revisions.body, node.created, node.status FROM node, node_revisions WHERE (node.type = 'blog' OR node.type = 'story') AND node.vid = node_revisions.vid"
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