fagiani-jekyll 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. data/History.txt +284 -0
  2. data/LICENSE +21 -0
  3. data/README.textile +41 -0
  4. data/Rakefile +159 -0
  5. data/bin/jekyll +192 -0
  6. data/cucumber.yml +1 -0
  7. data/features/create_sites.feature +94 -0
  8. data/features/embed_filters.feature +60 -0
  9. data/features/markdown.feature +30 -0
  10. data/features/pagination.feature +27 -0
  11. data/features/permalinks.feature +65 -0
  12. data/features/post_data.feature +153 -0
  13. data/features/site_configuration.feature +126 -0
  14. data/features/site_data.feature +82 -0
  15. data/features/step_definitions/jekyll_steps.rb +145 -0
  16. data/features/support/env.rb +16 -0
  17. data/jekyll.gemspec +140 -0
  18. data/lib/jekyll.rb +125 -0
  19. data/lib/jekyll/albino.rb +120 -0
  20. data/lib/jekyll/converter.rb +50 -0
  21. data/lib/jekyll/converters/identity.rb +22 -0
  22. data/lib/jekyll/converters/markdown.rb +113 -0
  23. data/lib/jekyll/converters/textile.rb +33 -0
  24. data/lib/jekyll/convertible.rb +98 -0
  25. data/lib/jekyll/core_ext.rb +52 -0
  26. data/lib/jekyll/errors.rb +6 -0
  27. data/lib/jekyll/filters.rb +53 -0
  28. data/lib/jekyll/generator.rb +7 -0
  29. data/lib/jekyll/generators/pagination.rb +87 -0
  30. data/lib/jekyll/layout.rb +36 -0
  31. data/lib/jekyll/migrators/csv.rb +26 -0
  32. data/lib/jekyll/migrators/drupal.rb +86 -0
  33. data/lib/jekyll/migrators/marley.rb +53 -0
  34. data/lib/jekyll/migrators/mephisto.rb +79 -0
  35. data/lib/jekyll/migrators/mt.rb +77 -0
  36. data/lib/jekyll/migrators/textpattern.rb +50 -0
  37. data/lib/jekyll/migrators/typo.rb +49 -0
  38. data/lib/jekyll/migrators/wordpress.com.rb +38 -0
  39. data/lib/jekyll/migrators/wordpress.rb +56 -0
  40. data/lib/jekyll/page.rb +134 -0
  41. data/lib/jekyll/plugin.rb +76 -0
  42. data/lib/jekyll/post.rb +244 -0
  43. data/lib/jekyll/site.rb +273 -0
  44. data/lib/jekyll/static_file.rb +75 -0
  45. data/lib/jekyll/tags/highlight.rb +73 -0
  46. data/lib/jekyll/tags/include.rb +37 -0
  47. data/test/helper.rb +34 -0
  48. data/test/source/.htaccess +8 -0
  49. data/test/source/_includes/sig.markdown +3 -0
  50. data/test/source/_layouts/default.html +27 -0
  51. data/test/source/_layouts/simple.html +1 -0
  52. data/test/source/_posts/2008-02-02-not-published.textile +8 -0
  53. data/test/source/_posts/2008-02-02-published.textile +8 -0
  54. data/test/source/_posts/2008-10-18-foo-bar.textile +8 -0
  55. data/test/source/_posts/2008-11-21-complex.textile +8 -0
  56. data/test/source/_posts/2008-12-03-permalinked-post.textile +9 -0
  57. data/test/source/_posts/2008-12-13-include.markdown +8 -0
  58. data/test/source/_posts/2009-01-27-array-categories.textile +10 -0
  59. data/test/source/_posts/2009-01-27-categories.textile +7 -0
  60. data/test/source/_posts/2009-01-27-category.textile +7 -0
  61. data/test/source/_posts/2009-01-27-empty-categories.textile +7 -0
  62. data/test/source/_posts/2009-01-27-empty-category.textile +7 -0
  63. data/test/source/_posts/2009-03-12-hash-#1.markdown +6 -0
  64. data/test/source/_posts/2009-05-18-empty-tag.textile +6 -0
  65. data/test/source/_posts/2009-05-18-empty-tags.textile +6 -0
  66. data/test/source/_posts/2009-05-18-tag.textile +6 -0
  67. data/test/source/_posts/2009-05-18-tags.textile +9 -0
  68. data/test/source/_posts/2009-06-22-empty-yaml.textile +3 -0
  69. data/test/source/_posts/2009-06-22-no-yaml.textile +1 -0
  70. data/test/source/_posts/2010-01-08-triple-dash.markdown +5 -0
  71. data/test/source/_posts/2010-01-09-date-override.textile +7 -0
  72. data/test/source/_posts/2010-01-09-time-override.textile +7 -0
  73. data/test/source/_posts/2010-01-09-timezone-override.textile +7 -0
  74. data/test/source/_posts/2010-01-16-override-data.textile +4 -0
  75. data/test/source/about.html +6 -0
  76. data/test/source/category/_posts/2008-9-23-categories.textile +6 -0
  77. data/test/source/contacts.html +5 -0
  78. data/test/source/css/screen.css +76 -0
  79. data/test/source/deal.with.dots.html +7 -0
  80. data/test/source/foo/_posts/bar/2008-12-12-topical-post.textile +8 -0
  81. data/test/source/index.html +22 -0
  82. data/test/source/sitemap.xml +32 -0
  83. data/test/source/win/_posts/2009-05-24-yaml-linebreak.markdown +7 -0
  84. data/test/source/z_category/_posts/2008-9-23-categories.textile +6 -0
  85. data/test/suite.rb +9 -0
  86. data/test/test_configuration.rb +29 -0
  87. data/test/test_core_ext.rb +66 -0
  88. data/test/test_filters.rb +53 -0
  89. data/test/test_generated_site.rb +72 -0
  90. data/test/test_kramdown.rb +23 -0
  91. data/test/test_page.rb +117 -0
  92. data/test/test_pager.rb +113 -0
  93. data/test/test_post.rb +396 -0
  94. data/test/test_rdiscount.rb +18 -0
  95. data/test/test_site.rb +186 -0
  96. data/test/test_tags.rb +127 -0
  97. metadata +332 -0
@@ -0,0 +1,22 @@
1
+ module Jekyll
2
+
3
+ class IdentityConverter < Converter
4
+ safe true
5
+
6
+ priority :lowest
7
+
8
+ def matches(ext)
9
+ true
10
+ end
11
+
12
+ def output_ext(ext)
13
+ ext
14
+ end
15
+
16
+ def convert(content)
17
+ content
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,113 @@
1
+ module Jekyll
2
+
3
+ class MarkdownConverter < Converter
4
+ safe true
5
+
6
+ pygments_prefix "\n"
7
+ pygments_suffix "\n"
8
+
9
+ def setup
10
+ return if @setup
11
+ # Set the Markdown interpreter (and Maruku self.config, if necessary)
12
+ case @config['markdown']
13
+ when 'kramdown'
14
+ begin
15
+ require 'kramdown'
16
+ rescue LoadError
17
+ STDERR.puts 'You are missing a library required for Markdown. Please run:'
18
+ STDERR.puts ' $ [sudo] gem install kramdown'
19
+ raise FatalException.new("Missing dependency: kramdown")
20
+ end
21
+ when 'rdiscount'
22
+ begin
23
+ require 'rdiscount'
24
+
25
+ # Load rdiscount extensions
26
+ @rdiscount_extensions = @config['rdiscount']['extensions'].map { |e| e.to_sym }
27
+ rescue LoadError
28
+ STDERR.puts 'You are missing a library required for Markdown. Please run:'
29
+ STDERR.puts ' $ [sudo] gem install rdiscount'
30
+ raise FatalException.new("Missing dependency: rdiscount")
31
+ end
32
+ when 'maruku'
33
+ begin
34
+ require 'maruku'
35
+
36
+ if @config['maruku']['use_divs']
37
+ require 'maruku/ext/div'
38
+ STDERR.puts 'Maruku: Using extended syntax for div elements.'
39
+ end
40
+
41
+ if @config['maruku']['use_tex']
42
+ require 'maruku/ext/math'
43
+ STDERR.puts "Maruku: Using LaTeX extension. Images in `#{@config['maruku']['png_dir']}`."
44
+
45
+ # Switch off MathML output
46
+ MaRuKu::Globals[:html_math_output_mathml] = false
47
+ MaRuKu::Globals[:html_math_engine] = 'none'
48
+
49
+ # Turn on math to PNG support with blahtex
50
+ # Resulting PNGs stored in `images/latex`
51
+ MaRuKu::Globals[:html_math_output_png] = true
52
+ MaRuKu::Globals[:html_png_engine] = @config['maruku']['png_engine']
53
+ MaRuKu::Globals[:html_png_dir] = @config['maruku']['png_dir']
54
+ MaRuKu::Globals[:html_png_url] = @config['maruku']['png_url']
55
+ end
56
+ rescue LoadError
57
+ STDERR.puts 'You are missing a library required for Markdown. Please run:'
58
+ STDERR.puts ' $ [sudo] gem install maruku'
59
+ raise FatalException.new("Missing dependency: maruku")
60
+ end
61
+ else
62
+ STDERR.puts "Invalid Markdown processor: #{@config['markdown']}"
63
+ STDERR.puts " Valid options are [ maruku | rdiscount | kramdown ]"
64
+ raise FatalException.new("Invalid Markdown process: #{@config['markdown']}")
65
+ end
66
+ @setup = true
67
+ end
68
+
69
+ def matches(ext)
70
+ ext =~ /(markdown|mkdn?|md)/i
71
+ end
72
+
73
+ def output_ext(ext)
74
+ ".html"
75
+ end
76
+
77
+ def convert(content)
78
+ setup
79
+ case @config['markdown']
80
+ when 'kramdown'
81
+ # Check for use of coderay
82
+ if @config['kramdown']['use_coderay']
83
+ Kramdown::Document.new(content, {
84
+ :auto_ids => @config['kramdown']['auto_ids'],
85
+ :footnote_nr => @config['kramdown']['footnote_nr'],
86
+ :entity_output => @config['kramdown']['entity_output'],
87
+ :toc_levels => @config['kramdown']['toc_levels'],
88
+
89
+ :coderay_wrap => @config['kramdown']['coderay']['coderay_wrap'],
90
+ :coderay_line_numbers => @config['kramdown']['coderay']['coderay_line_numbers'],
91
+ :coderay_line_number_start => @config['kramdown']['coderay']['coderay_line_number_start'],
92
+ :coderay_tab_width => @config['kramdown']['coderay']['coderay_tab_width'],
93
+ :coderay_bold_every => @config['kramdown']['coderay']['coderay_bold_every'],
94
+ :coderay_css => @config['kramdown']['coderay']['coderay_css']
95
+ }).to_html
96
+ else
97
+ # not using coderay
98
+ Kramdown::Document.new(content, {
99
+ :auto_ids => @config['kramdown']['auto_ids'],
100
+ :footnote_nr => @config['kramdown']['footnote_nr'],
101
+ :entity_output => @config['kramdown']['entity_output'],
102
+ :toc_levels => @config['kramdown']['toc_levels']
103
+ }).to_html
104
+ end
105
+ when 'rdiscount'
106
+ RDiscount.new(content, *@rdiscount_extensions).to_html
107
+ when 'maruku'
108
+ Maruku.new(content).to_html
109
+ end
110
+ end
111
+ end
112
+
113
+ end
@@ -0,0 +1,33 @@
1
+ module Jekyll
2
+
3
+ class TextileConverter < Converter
4
+ safe true
5
+
6
+ pygments_prefix '<notextile>'
7
+ pygments_suffix '</notextile>'
8
+
9
+ def setup
10
+ return if @setup
11
+ require 'redcloth'
12
+ @setup = true
13
+ rescue LoadError
14
+ STDERR.puts 'You are missing a library required for Textile. Please run:'
15
+ STDERR.puts ' $ [sudo] gem install RedCloth'
16
+ raise FatalException.new("Missing dependency: RedCloth")
17
+ end
18
+
19
+ def matches(ext)
20
+ ext =~ /textile/i
21
+ end
22
+
23
+ def output_ext(ext)
24
+ ".html"
25
+ end
26
+
27
+ def convert(content)
28
+ setup
29
+ RedCloth.new(content).to_html
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,98 @@
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
6
+ # self.content
7
+ # self.content=
8
+ # self.data=
9
+ # self.ext=
10
+ # self.output=
11
+ module Jekyll
12
+ module Convertible
13
+ # Return the contents as a string
14
+ def to_s
15
+ self.content || ''
16
+ end
17
+
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
21
+ #
22
+ # Returns nothing
23
+ def read_yaml(base, name)
24
+ self.content = File.read(File.join(base, name))
25
+
26
+ if self.content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
27
+ self.content = self.content[($1.size + $2.size)..-1]
28
+
29
+ begin
30
+ self.data = YAML.load($1)
31
+ rescue => e
32
+ puts "YAML Exception: #{e.message}"
33
+ end
34
+ end
35
+
36
+ self.data ||= {}
37
+ end
38
+
39
+ # Transform the contents based on the content type.
40
+ #
41
+ # Returns nothing
42
+ def transform
43
+ self.content = converter.convert(self.content)
44
+ end
45
+
46
+ # Determine the extension depending on content_type
47
+ #
48
+ # Returns the extensions for the output file
49
+ def output_ext
50
+ converter.output_ext(self.ext)
51
+ end
52
+
53
+ # Determine which converter to use based on this convertible's
54
+ # extension
55
+ def converter
56
+ @converter ||= self.site.converters.find { |c| c.matches(self.ext) }
57
+ end
58
+
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
62
+ #
63
+ # Returns nothing
64
+ def do_layout(payload, layouts)
65
+ info = { :filters => [Jekyll::Filters], :registers => { :site => self.site } }
66
+
67
+ # render and transform content (this becomes the final content of the object)
68
+ payload["pygments_prefix"] = converter.pygments_prefix
69
+ payload["pygments_suffix"] = converter.pygments_suffix
70
+
71
+ begin
72
+ self.content = Liquid::Template.parse(self.content).render(payload, info)
73
+ rescue => e
74
+ puts "Liquid Exception: #{e.message} in #{self.data["layout"]}"
75
+ end
76
+
77
+ self.transform
78
+
79
+ # output keeps track of what will finally be written
80
+ self.output = self.content
81
+
82
+ # recursively render layouts
83
+ layout = layouts[self.data["layout"]]
84
+ while layout
85
+ payload = payload.deep_merge({"content" => self.output, "page" => layout.data})
86
+
87
+ begin
88
+ content = converter.convert(layout.content)
89
+ self.output = Liquid::Template.parse(content).render(payload, info)
90
+ rescue => e
91
+ puts "Liquid Exception: #{e.message} in #{self.data["layout"]}"
92
+ end
93
+
94
+ layout = layouts[layout.data["layout"]]
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,52 @@
1
+ class Hash
2
+ # Merges self with another hash, recursively.
3
+ #
4
+ # This code was lovingly stolen from some random gem:
5
+ # http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
6
+ #
7
+ # Thanks to whoever made it.
8
+ def deep_merge(hash)
9
+ target = dup
10
+
11
+ hash.keys.each do |key|
12
+ if hash[key].is_a? Hash and self[key].is_a? Hash
13
+ target[key] = target[key].deep_merge(hash[key])
14
+ next
15
+ end
16
+
17
+ target[key] = hash[key]
18
+ end
19
+
20
+ target
21
+ end
22
+
23
+ # Read array from the supplied hash favouring the singular key
24
+ # and then the plural key, and handling any nil entries.
25
+ # +hash+ the hash to read from
26
+ # +singular_key+ the singular key
27
+ # +plural_key+ the singular key
28
+ #
29
+ # Returns an array
30
+ def pluralized_array(singular_key, plural_key)
31
+ hash = self
32
+ if hash.has_key?(singular_key)
33
+ array = [hash[singular_key]] if hash[singular_key]
34
+ elsif hash.has_key?(plural_key)
35
+ case hash[plural_key]
36
+ when String
37
+ array = hash[plural_key].split
38
+ when Array
39
+ array = hash[plural_key].compact
40
+ end
41
+ end
42
+ array || []
43
+ end
44
+ end
45
+
46
+ # Thanks, ActiveSupport!
47
+ class Date
48
+ # Converts datetime to an appropriate format for use in XML
49
+ def xmlschema
50
+ strftime("%Y-%m-%dT%H:%M:%S%Z")
51
+ end if RUBY_VERSION < '1.9'
52
+ end
@@ -0,0 +1,6 @@
1
+ module Jekyll
2
+
3
+ class FatalException < StandardError
4
+ end
5
+
6
+ end
@@ -0,0 +1,53 @@
1
+ require 'uri'
2
+
3
+ module Jekyll
4
+
5
+ module Filters
6
+ def textilize(input)
7
+ TextileConverter.new.convert(input)
8
+ end
9
+
10
+ def date_to_string(date)
11
+ date.strftime("%d %b %Y")
12
+ end
13
+
14
+ def date_to_long_string(date)
15
+ date.strftime("%d %B %Y")
16
+ end
17
+
18
+ def date_to_xmlschema(date)
19
+ date.xmlschema
20
+ end
21
+
22
+ def xml_escape(input)
23
+ CGI.escapeHTML(input)
24
+ end
25
+
26
+ def cgi_escape(input)
27
+ CGI::escape(input)
28
+ end
29
+
30
+ def uri_escape(input)
31
+ URI.escape(input)
32
+ end
33
+
34
+ def number_of_words(input)
35
+ input.split.length
36
+ end
37
+
38
+ def array_to_sentence_string(array)
39
+ connector = "and"
40
+ case array.length
41
+ when 0
42
+ ""
43
+ when 1
44
+ array[0].to_s
45
+ when 2
46
+ "#{array[0]} #{connector} #{array[1]}"
47
+ else
48
+ "#{array[0...-1].join(', ')}, #{connector} #{array[-1]}"
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,7 @@
1
+ module Jekyll
2
+
3
+ class Generator < Plugin
4
+
5
+ end
6
+
7
+ end
@@ -0,0 +1,87 @@
1
+ module Jekyll
2
+
3
+ class Pagination < Generator
4
+ safe true
5
+
6
+ def generate(site)
7
+ site.pages.dup.each do |page|
8
+ paginate(site, page) if Pager.pagination_enabled?(site.config, page.name)
9
+ end
10
+ end
11
+
12
+ # 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
14
+ # site-wide data.
15
+ # +page+ is the index.html Page that requires pagination
16
+ #
17
+ # {"paginator" => { "page" => <Number>,
18
+ # "per_page" => <Number>,
19
+ # "posts" => [<Post>],
20
+ # "total_posts" => <Number>,
21
+ # "total_pages" => <Number>,
22
+ # "previous_page" => <Number>,
23
+ # "next_page" => <Number> }}
24
+ def paginate(site, page)
25
+ all_posts = site.site_payload['site']['posts']
26
+ pages = Pager.calculate_pages(all_posts, site.config['paginate'].to_i)
27
+ (1..pages).each do |num_page|
28
+ pager = Pager.new(site.config, num_page, all_posts, pages)
29
+ if num_page > 1
30
+ newpage = Page.new(site, site.source, page.dir, page.name)
31
+ newpage.pager = pager
32
+ newpage.dir = File.join(page.dir, "page#{num_page}")
33
+ site.pages << newpage
34
+ else
35
+ page.pager = pager
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ class Pager
43
+ attr_reader :page, :per_page, :posts, :total_posts, :total_pages, :previous_page, :next_page
44
+
45
+ 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
49
+ end
50
+
51
+ def self.pagination_enabled?(config, file)
52
+ file == 'index.html' && !config['paginate'].nil?
53
+ end
54
+
55
+ def initialize(config, page, all_posts, num_pages = nil)
56
+ @page = page
57
+ @per_page = config['paginate'].to_i
58
+ @total_pages = num_pages || Pager.calculate_pages(all_posts, @per_page)
59
+
60
+ if @page > @total_pages
61
+ raise RuntimeError, "page number can't be greater than total pages: #{@page} > #{@total_pages}"
62
+ end
63
+
64
+ init = (@page - 1) * @per_page
65
+ offset = (init + @per_page - 1) >= all_posts.size ? all_posts.size : (init + @per_page - 1)
66
+
67
+ @total_posts = all_posts.size
68
+ @posts = all_posts[init..offset]
69
+ @previous_page = @page != 1 ? @page - 1 : nil
70
+ @next_page = @page != @total_pages ? @page + 1 : nil
71
+ end
72
+
73
+ def to_liquid
74
+ {
75
+ 'page' => page,
76
+ 'per_page' => per_page,
77
+ 'posts' => posts,
78
+ 'total_posts' => total_posts,
79
+ 'total_pages' => total_pages,
80
+ 'previous_page' => previous_page,
81
+ 'next_page' => next_page
82
+ }
83
+ end
84
+ end
85
+
86
+
87
+ end