jekyll 1.5.1 → 2.0.0.alpha.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.

Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.markdown +6 -6
  3. data/History.markdown +99 -23
  4. data/README.markdown +7 -3
  5. data/Rakefile +5 -5
  6. data/bin/jekyll +101 -116
  7. data/features/embed_filters.feature +13 -0
  8. data/features/include_tag.feature +11 -0
  9. data/features/markdown.feature +3 -3
  10. data/features/site_configuration.feature +34 -3
  11. data/features/step_definitions/jekyll_steps.rb +47 -34
  12. data/features/support/env.rb +25 -28
  13. data/jekyll.gemspec +38 -18
  14. data/lib/jekyll.rb +7 -15
  15. data/lib/jekyll/commands/build.rb +2 -0
  16. data/lib/jekyll/commands/serve.rb +11 -1
  17. data/lib/jekyll/configuration.rb +22 -6
  18. data/lib/jekyll/converter.rb +16 -16
  19. data/lib/jekyll/converters/markdown.rb +30 -15
  20. data/lib/jekyll/converters/markdown/maruku_parser.rb +4 -5
  21. data/lib/jekyll/converters/markdown/redcarpet_parser.rb +34 -3
  22. data/lib/jekyll/converters/sass.rb +58 -0
  23. data/lib/jekyll/converters/textile.rb +2 -2
  24. data/lib/jekyll/convertible.rb +25 -6
  25. data/lib/jekyll/core_ext.rb +0 -35
  26. data/lib/jekyll/deprecator.rb +2 -2
  27. data/lib/jekyll/entry_filter.rb +61 -25
  28. data/lib/jekyll/excerpt.rb +8 -6
  29. data/lib/jekyll/filters.rb +46 -2
  30. data/lib/jekyll/layout_reader.rb +40 -0
  31. data/lib/jekyll/mime.types +19 -9
  32. data/lib/jekyll/page.rb +6 -4
  33. data/lib/jekyll/post.rb +11 -18
  34. data/lib/jekyll/site.rb +34 -32
  35. data/lib/jekyll/tags/highlight.rb +26 -4
  36. data/lib/jekyll/tags/include.rb +29 -17
  37. data/lib/jekyll/tags/post_url.rb +10 -1
  38. data/lib/jekyll/url.rb +0 -2
  39. data/lib/site_template/_config.yml +1 -1
  40. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +1 -1
  41. data/lib/site_template/css/main.css +8 -1
  42. data/script/bootstrap +2 -0
  43. data/script/branding +11 -0
  44. data/script/cibuild +5 -0
  45. data/script/rebund +140 -0
  46. data/site/_config.yml +2 -2
  47. data/site/_data/docs.yml +44 -0
  48. data/site/{css → _includes/css}/gridism.css +0 -0
  49. data/site/_includes/css/normalize.css +1 -0
  50. data/site/{css → _includes/css}/pygments.css +2 -0
  51. data/site/{css → _includes/css}/style.css +10 -0
  52. data/site/_includes/docs_contents.html +4 -12
  53. data/site/_includes/docs_contents_mobile.html +4 -17
  54. data/site/_includes/docs_option.html +1 -1
  55. data/site/_includes/docs_ul.html +2 -2
  56. data/site/_includes/footer.html +1 -1
  57. data/site/_includes/top.html +1 -4
  58. data/site/_layouts/news_item.html +2 -2
  59. data/site/_posts/2013-07-24-jekyll-1-1-1-released.markdown +4 -4
  60. data/site/_posts/2013-09-14-jekyll-1-2-1-released.markdown +1 -1
  61. data/site/_posts/2013-10-28-jekyll-1-3-0-rc1-released.markdown +1 -1
  62. data/site/_posts/2013-12-09-jekyll-1-4-1-released.markdown +20 -0
  63. data/site/_posts/2014-01-13-jekyll-1-4-3-released.markdown +1 -2
  64. data/site/css/screen.css +27 -0
  65. data/site/docs/assets.md +46 -0
  66. data/site/docs/configuration.md +18 -4
  67. data/site/docs/contributing.md +2 -2
  68. data/site/docs/datafiles.md +6 -6
  69. data/site/docs/deployment-methods.md +5 -0
  70. data/site/docs/extras.md +38 -2
  71. data/site/docs/frontmatter.md +2 -1
  72. data/site/docs/history.md +0 -22
  73. data/site/docs/installation.md +7 -7
  74. data/site/docs/migrations.md +1 -1
  75. data/site/docs/plugins.md +11 -2
  76. data/site/docs/posts.md +25 -4
  77. data/site/docs/sites.md +1 -1
  78. data/site/docs/structure.md +1 -1
  79. data/site/docs/templates.md +13 -8
  80. data/site/docs/troubleshooting.md +8 -5
  81. data/site/docs/usage.md +11 -0
  82. data/site/docs/variables.md +18 -0
  83. data/site/docs/windows.md +44 -0
  84. data/test/helper.rb +5 -8
  85. data/test/source/_includes/include.html +1 -0
  86. data/test/source/_includes/sig.markdown +2 -2
  87. data/test/source/_posts/2013-12-17-include-variable-filters.markdown +21 -0
  88. data/test/source/_posts/2013-12-20-properties.text +11 -0
  89. data/test/source/_sass/_grid.scss +1 -0
  90. data/test/source/css/main.scss +4 -0
  91. data/test/source/js/coffeescript.coffee +10 -0
  92. data/test/source/properties.html +8 -0
  93. data/test/source/unpublished.html +7 -0
  94. data/test/test_coffeescript.rb +49 -0
  95. data/test/test_configuration.rb +29 -18
  96. data/test/test_convertible.rb +7 -9
  97. data/test/test_core_ext.rb +0 -22
  98. data/test/test_entry_filter.rb +36 -2
  99. data/test/test_excerpt.rb +43 -1
  100. data/test/test_filters.rb +44 -5
  101. data/test/test_generated_site.rb +5 -1
  102. data/test/test_layout_reader.rb +17 -0
  103. data/test/test_page.rb +28 -10
  104. data/test/test_post.rb +32 -15
  105. data/test/test_redcarpet.rb +19 -3
  106. data/test/test_sass.rb +122 -0
  107. data/test/test_site.rb +56 -7
  108. data/test/test_tags.rb +102 -51
  109. metadata +154 -80
  110. data/site/_posts/2014-03-24-jekyll-1-5-0-released.markdown +0 -19
  111. data/site/_posts/2014-03-27-jekyll-1-5-1-released.markdown +0 -26
  112. data/site/css/normalize.css +0 -1
  113. data/test/source/_posts/2014-01-06-permalink-traversal.md +0 -5
  114. data/test/source/exploit.md +0 -5
  115. data/test/test_path_sanitization.rb +0 -18
@@ -18,7 +18,7 @@ require 'rubygems'
18
18
  # stdlib
19
19
  require 'fileutils'
20
20
  require 'time'
21
- require 'safe_yaml'
21
+ require 'safe_yaml/load'
22
22
  require 'English'
23
23
  require 'pathname'
24
24
 
@@ -27,6 +27,7 @@ require 'liquid'
27
27
  require 'maruku'
28
28
  require 'colorator'
29
29
  require 'toml'
30
+ require 'sass'
30
31
 
31
32
  # internal requires
32
33
  require 'jekyll/core_ext'
@@ -47,6 +48,7 @@ require 'jekyll/errors'
47
48
  require 'jekyll/related_posts'
48
49
  require 'jekyll/cleaner'
49
50
  require 'jekyll/entry_filter'
51
+ require 'jekyll/layout_reader'
50
52
 
51
53
  # extensions
52
54
  require 'jekyll/plugin'
@@ -60,10 +62,13 @@ require_all 'jekyll/converters/markdown'
60
62
  require_all 'jekyll/generators'
61
63
  require_all 'jekyll/tags'
62
64
 
65
+ # plugins
66
+ require 'jekyll-coffeescript'
67
+
63
68
  SafeYAML::OPTIONS[:suppress_warnings] = true
64
69
 
65
70
  module Jekyll
66
- VERSION = '1.5.1'
71
+ VERSION = '2.0.0.alpha.1'
67
72
 
68
73
  # Public: Generate a Jekyll configuration Hash by merging the default
69
74
  # options with anything in _config.yml, and adding the given options on top.
@@ -97,17 +102,4 @@ module Jekyll
97
102
  def self.logger
98
103
  @logger ||= Stevenson.new
99
104
  end
100
-
101
- # Get a subpath without any of the traversal nonsense.
102
- #
103
- # Returns a pure and clean path
104
- def self.sanitized_path(base_directory, questionable_path)
105
- clean_path = File.expand_path(questionable_path, "/")
106
- clean_path.gsub!(/\A\w\:\//, '/')
107
- unless clean_path.start_with?(base_directory)
108
- File.join(base_directory, clean_path)
109
- else
110
- clean_path
111
- end
112
- end
113
105
  end
@@ -4,6 +4,8 @@ module Jekyll
4
4
  def self.process(options)
5
5
  site = Jekyll::Site.new(options)
6
6
 
7
+ Jekyll.logger.log_level = Jekyll::Stevenson::ERROR if options['quiet']
8
+
7
9
  self.build(site, options)
8
10
  self.watch(site, options) if options['watch']
9
11
  end
@@ -10,6 +10,15 @@ module Jekyll
10
10
 
11
11
  FileUtils.mkdir_p(destination)
12
12
 
13
+ # monkey patch WEBrick using custom 404 page (/404.html)
14
+ if File.exists?(File.join(destination, '404.html'))
15
+ WEBrick::HTTPResponse.class_eval do
16
+ def create_error_page
17
+ @body = IO.read(File.join(@config[:DocumentRoot], '404.html'))
18
+ end
19
+ end
20
+ end
21
+
13
22
  # recreate NondisclosureName under utf-8 circumstance
14
23
  fh_option = WEBrick::Config::FileHandler
15
24
  fh_option[:NondisclosureName] = ['.ht*','~*']
@@ -23,7 +32,7 @@ module Jekyll
23
32
  if options['detach'] # detach the server
24
33
  pid = Process.fork { s.start }
25
34
  Process.detach(pid)
26
- Jekyll.logger.info "Server detatched with pid '#{pid}'.", "Run `kill -9 #{pid}' to stop the server."
35
+ Jekyll.logger.info "Server detached with pid '#{pid}'.", "Run `kill -9 #{pid}' to stop the server."
27
36
  else # create a new server thread, then join it with current terminal
28
37
  t = Thread.new { s.start }
29
38
  trap("INT") { s.shutdown }
@@ -33,6 +42,7 @@ module Jekyll
33
42
 
34
43
  def self.webrick_options(config)
35
44
  opts = {
45
+ :DocumentRoot => config['destination'],
36
46
  :Port => config['port'],
37
47
  :BindAddress => config['host'],
38
48
  :MimeTypes => self.mime_types,
@@ -16,7 +16,7 @@ module Jekyll
16
16
 
17
17
  'timezone' => nil, # use the local timezone
18
18
 
19
- 'encoding' => nil, # use the system encoding
19
+ 'encoding' => 'utf-8', # always use utf-8 encoding. NEVER FORGET
20
20
 
21
21
  'safe' => false,
22
22
  'detach' => false, # default to not detaching the server
@@ -24,12 +24,12 @@ module Jekyll
24
24
  'limit_posts' => 0,
25
25
  'lsi' => false,
26
26
  'future' => true, # remove and make true just default
27
- 'pygments' => true,
28
27
 
29
28
  'relative_permalinks' => true, # backwards-compatibility with < 1.0
30
29
  # will be set to false once 2.0 hits
31
30
 
32
- 'markdown' => 'maruku',
31
+ 'markdown' => 'kramdown',
32
+ 'highlighter' => 'pygments',
33
33
  'permalink' => 'date',
34
34
  'baseurl' => '/',
35
35
  'include' => ['.htaccess'],
@@ -45,12 +45,12 @@ module Jekyll
45
45
  'excerpt_separator' => "\n\n",
46
46
 
47
47
  'maruku' => {
48
- 'fenced_code_blocks' => true,
49
48
  'use_tex' => false,
50
49
  'use_divs' => false,
51
50
  'png_engine' => 'blahtex',
52
51
  'png_dir' => 'images/latex',
53
- 'png_url' => '/images/latex'
52
+ 'png_url' => '/images/latex',
53
+ 'fenced_code_blocks' => true
54
54
  },
55
55
 
56
56
  'rdiscount' => {
@@ -105,7 +105,7 @@ module Jekyll
105
105
  when '.toml'
106
106
  TOML.load_file(filename)
107
107
  when /\.y(a)?ml/
108
- YAML.safe_load_file(filename)
108
+ SafeYAML.load_file(filename)
109
109
  else
110
110
  raise ArgumentError, "No parser for '#{filename}' is available. Use a .toml or .y(a)ml file instead."
111
111
  end
@@ -210,6 +210,16 @@ module Jekyll
210
210
  config.delete('server_port')
211
211
  end
212
212
 
213
+ if config.has_key? 'pygments'
214
+ Jekyll.logger.warn "Deprecation:", "The 'pygments' configuration option" +
215
+ " has been renamed to 'highlighter'. Please update your" +
216
+ " config file accordingly. The allowed values are 'rouge', " +
217
+ "'pygments' or null."
218
+
219
+ config['highlighter'] = 'pygments' if config['pygments']
220
+ config.delete('pygments')
221
+ end
222
+
213
223
  %w[include exclude].each do |option|
214
224
  if config.fetch(option, []).is_a?(String)
215
225
  Jekyll.logger.warn "Deprecation:", "The '#{option}' configuration option" +
@@ -219,6 +229,12 @@ module Jekyll
219
229
  config[option] = csv_to_array(config[option])
220
230
  end
221
231
  end
232
+
233
+ if config.fetch('markdown', 'kramdown').to_s.downcase.eql?("maruku")
234
+ Jekyll::Deprecator.deprecation_message "You're using the 'maruku' " +
235
+ "Markdown processor. Maruku support has been deprecated and will " +
236
+ "be removed in 3.0.0. We recommend you switch to Kramdown."
237
+ end
222
238
  config
223
239
  end
224
240
 
@@ -1,27 +1,27 @@
1
1
  module Jekyll
2
2
  class Converter < Plugin
3
- # Public: Get or set the pygments prefix. When an argument is specified,
3
+ # Public: Get or set the highlighter prefix. When an argument is specified,
4
4
  # the prefix will be set. If no argument is specified, the current prefix
5
5
  # will be returned.
6
6
  #
7
- # pygments_prefix - The String prefix (default: nil).
7
+ # highlighter_prefix - The String prefix (default: nil).
8
8
  #
9
9
  # Returns the String prefix.
10
- def self.pygments_prefix(pygments_prefix = nil)
11
- @pygments_prefix = pygments_prefix if pygments_prefix
12
- @pygments_prefix
10
+ def self.highlighter_prefix(highlighter_prefix = nil)
11
+ @highlighter_prefix = highlighter_prefix if highlighter_prefix
12
+ @highlighter_prefix
13
13
  end
14
14
 
15
- # Public: Get or set the pygments suffix. When an argument is specified,
15
+ # Public: Get or set the highlighter suffix. When an argument is specified,
16
16
  # the suffix will be set. If no argument is specified, the current suffix
17
17
  # will be returned.
18
18
  #
19
- # pygments_suffix - The String suffix (default: nil).
19
+ # highlighter_suffix - The String suffix (default: nil).
20
20
  #
21
21
  # Returns the String suffix.
22
- def self.pygments_suffix(pygments_suffix = nil)
23
- @pygments_suffix = pygments_suffix if pygments_suffix
24
- @pygments_suffix
22
+ def self.highlighter_suffix(highlighter_suffix = nil)
23
+ @highlighter_suffix = highlighter_suffix if highlighter_suffix
24
+ @highlighter_suffix
25
25
  end
26
26
 
27
27
  # Initialize the converter.
@@ -31,18 +31,18 @@ module Jekyll
31
31
  @config = config
32
32
  end
33
33
 
34
- # Get the pygments prefix.
34
+ # Get the highlighter prefix.
35
35
  #
36
36
  # Returns the String prefix.
37
- def pygments_prefix
38
- self.class.pygments_prefix
37
+ def highlighter_prefix
38
+ self.class.highlighter_prefix
39
39
  end
40
40
 
41
- # Get the pygments suffix.
41
+ # Get the highlighter suffix.
42
42
  #
43
43
  # Returns the String suffix.
44
- def pygments_suffix
45
- self.class.pygments_suffix
44
+ def highlighter_suffix
45
+ self.class.highlighter_suffix
46
46
  end
47
47
  end
48
48
  end
@@ -3,25 +3,27 @@ module Jekyll
3
3
  class Markdown < Converter
4
4
  safe true
5
5
 
6
- pygments_prefix "\n"
7
- pygments_suffix "\n"
6
+ highlighter_prefix "\n"
7
+ highlighter_suffix "\n"
8
8
 
9
9
  def setup
10
10
  return if @setup
11
- @parser = case @config['markdown']
12
- when 'redcarpet'
13
- RedcarpetParser.new @config
14
- when 'kramdown'
15
- KramdownParser.new @config
16
- when 'rdiscount'
17
- RDiscountParser.new @config
18
- when 'maruku'
19
- MarukuParser.new @config
11
+ @parser =
12
+ case @config['markdown'].downcase
13
+ when 'redcarpet' then RedcarpetParser.new(@config)
14
+ when 'kramdown' then KramdownParser.new(@config)
15
+ when 'rdiscount' then RDiscountParser.new(@config)
16
+ when 'maruku' then MarukuParser.new(@config)
20
17
  else
21
- STDERR.puts "Invalid Markdown processor: #{@config['markdown']}"
22
- STDERR.puts " Valid options are [ maruku | rdiscount | kramdown | redcarpet ]"
23
- raise FatalException.new("Invalid Markdown process: #{@config['markdown']}")
24
- end
18
+ # So they can't try some tricky bullshit or go down the ancestor chain, I hope.
19
+ if allowed_custom_class?(@config['markdown'])
20
+ self.class.const_get(@config['markdown']).new(@config)
21
+ else
22
+ Jekyll.logger.error "Invalid Markdown Processor:", "#{@config['markdown']}"
23
+ Jekyll.logger.error "", "Valid options are [ maruku | rdiscount | kramdown | redcarpet ]"
24
+ raise FatalException, "Invalid Markdown Processor: #{@config['markdown']}"
25
+ end
26
+ end
25
27
  @setup = true
26
28
  end
27
29
 
@@ -38,6 +40,19 @@ module Jekyll
38
40
  setup
39
41
  @parser.convert(content)
40
42
  end
43
+
44
+ private
45
+
46
+ # Private: Determine whether a class name is an allowed custom markdown
47
+ # class name
48
+ #
49
+ # parser_name - the name of the parser class
50
+ #
51
+ # Returns true if the parser name contains only alphanumeric characters
52
+ # and is defined within Jekyll::Converters::Markdown
53
+ def allowed_custom_class?(parser_name)
54
+ parser_name !~ /[^A-Za-z0-9]/ && self.class.constants.include?(parser_name.to_sym)
55
+ end
41
56
  end
42
57
  end
43
58
  end
@@ -8,7 +8,10 @@ module Jekyll
8
8
  @errors = []
9
9
  load_divs_library if @config['maruku']['use_divs']
10
10
  load_blahtext_library if @config['maruku']['use_tex']
11
- enable_fenced_code_blocks if @config['maruku']['fenced_code_blocks']
11
+
12
+ # allow fenced code blocks (new in Maruku 0.7.0)
13
+ MaRuKu::Globals[:fenced_code_blocks] = !!@config['maruku']['fenced_code_blocks']
14
+
12
15
  rescue LoadError
13
16
  STDERR.puts 'You are missing a library required for Markdown. Please run:'
14
17
  STDERR.puts ' $ [sudo] gem install maruku'
@@ -36,10 +39,6 @@ module Jekyll
36
39
  MaRuKu::Globals[:html_png_url] = @config['maruku']['png_url']
37
40
  end
38
41
 
39
- def enable_fenced_code_blocks
40
- MaRuKu::Globals[:fenced_code_blocks] = true
41
- end
42
-
43
42
  def print_errors_and_fail
44
43
  print @errors.join
45
44
  raise MaRuKu::Exception, "MaRuKu encountered problem(s) while converting your markup."
@@ -22,7 +22,7 @@ module Jekyll
22
22
  end
23
23
  end
24
24
 
25
- module WithoutPygments
25
+ module WithoutHighlighting
26
26
  require 'cgi'
27
27
 
28
28
  include CommonMethods
@@ -37,19 +37,50 @@ module Jekyll
37
37
  end
38
38
  end
39
39
 
40
+ module WithRouge
41
+ require 'rouge'
42
+ require 'rouge/plugins/redcarpet'
43
+
44
+ if Rouge.version < '1.3.0'
45
+ abort "Please install Rouge 1.3.0 or greater and try running Jekyll again."
46
+ end
47
+
48
+ include Rouge::Plugins::Redcarpet
49
+ include CommonMethods
50
+
51
+ def block_code(code, lang)
52
+ code = "<pre>#{super}</pre>"
53
+
54
+ output = "<div class=\"highlight\">"
55
+ output << add_code_tags(code, lang)
56
+ output << "</div>"
57
+ end
58
+
59
+ protected
60
+ def rouge_formatter(opts = {})
61
+ Rouge::Formatters::HTML.new(opts.merge(wrap: false))
62
+ end
63
+ end
64
+
65
+
40
66
  def initialize(config)
41
67
  require 'redcarpet'
42
68
  @config = config
43
69
  @redcarpet_extensions = {}
44
70
  @config['redcarpet']['extensions'].each { |e| @redcarpet_extensions[e.to_sym] = true }
45
71
 
46
- @renderer ||= if @config['pygments']
72
+ @renderer ||= case @config['highlighter']
73
+ when 'pygments'
47
74
  Class.new(Redcarpet::Render::HTML) do
48
75
  include WithPygments
49
76
  end
77
+ when 'rouge'
78
+ Class.new(Redcarpet::Render::HTML) do
79
+ include WithRouge
80
+ end
50
81
  else
51
82
  Class.new(Redcarpet::Render::HTML) do
52
- include WithoutPygments
83
+ include WithoutHighlighting
53
84
  end
54
85
  end
55
86
  rescue LoadError
@@ -0,0 +1,58 @@
1
+ module Jekyll
2
+ class Sass < Converter
3
+ safe true
4
+ priority :low
5
+
6
+ def matches(ext)
7
+ ext =~ /^\.s(a|c)ss$/i
8
+ end
9
+
10
+ def output_ext(ext)
11
+ ".css"
12
+ end
13
+
14
+ def jekyll_sass_configuration
15
+ @config["sass"] || {}
16
+ end
17
+
18
+ def sass_build_configuration_options(overrides)
19
+ jekyll_sass_configuration.deep_merge(overrides).symbolize_keys
20
+ end
21
+
22
+ def syntax_type_of_content(content)
23
+ if content.include?(";") || content.include?("{")
24
+ :scss
25
+ else
26
+ :sass
27
+ end
28
+ end
29
+
30
+ def sass_dir
31
+ return "_sass" if jekyll_sass_configuration["sass_dir"].to_s.empty?
32
+ jekyll_sass_configuration["sass_dir"]
33
+ end
34
+
35
+ def sass_dir_relative_to_site_source
36
+ File.join(
37
+ @config["source"],
38
+ File.expand_path(sass_dir, "/") # FIXME: Not windows-compatible
39
+ )
40
+ end
41
+
42
+ def allow_caching?
43
+ !@config["safe"]
44
+ end
45
+
46
+ def sass_configs(content = "")
47
+ sass_build_configuration_options({
48
+ "syntax" => syntax_type_of_content(content),
49
+ "cache" => allow_caching?,
50
+ "load_paths" => [sass_dir_relative_to_site_source]
51
+ })
52
+ end
53
+
54
+ def convert(content)
55
+ ::Sass.compile(content, sass_configs(content))
56
+ end
57
+ end
58
+ end
@@ -3,8 +3,8 @@ module Jekyll
3
3
  class Textile < Converter
4
4
  safe true
5
5
 
6
- pygments_prefix '<notextile>'
7
- pygments_suffix '</notextile>'
6
+ highlighter_prefix '<notextile>'
7
+ highlighter_suffix '</notextile>'
8
8
 
9
9
  def setup
10
10
  return if @setup