jekyll 3.0.5 → 3.1.0.pre.beta1
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.
- checksums.yaml +4 -4
- data/README.markdown +1 -1
- data/lib/jekyll.rb +6 -5
- data/lib/jekyll/cleaner.rb +1 -1
- data/lib/jekyll/collection.rb +8 -11
- data/lib/jekyll/commands/clean.rb +2 -2
- data/lib/jekyll/commands/doctor.rb +23 -1
- data/lib/jekyll/commands/serve.rb +148 -103
- data/lib/jekyll/commands/serve/servlet.rb +61 -0
- data/lib/jekyll/configuration.rb +26 -46
- data/lib/jekyll/converters/markdown.rb +51 -36
- data/lib/jekyll/converters/markdown/kramdown_parser.rb +70 -17
- data/lib/jekyll/convertible.rb +5 -4
- data/lib/jekyll/document.rb +19 -63
- data/lib/jekyll/drops/collection_drop.rb +24 -0
- data/lib/jekyll/drops/document_drop.rb +28 -0
- data/lib/jekyll/drops/drop.rb +128 -0
- data/lib/jekyll/drops/jekyll_drop.rb +21 -0
- data/lib/jekyll/drops/site_drop.rb +39 -0
- data/lib/jekyll/drops/unified_payload_drop.rb +26 -0
- data/lib/jekyll/drops/url_drop.rb +51 -0
- data/lib/jekyll/entry_filter.rb +1 -1
- data/lib/jekyll/errors.rb +3 -4
- data/lib/jekyll/excerpt.rb +0 -2
- data/lib/jekyll/external.rb +1 -0
- data/lib/jekyll/filters.rb +10 -0
- data/lib/jekyll/frontmatter_defaults.rb +8 -1
- data/lib/jekyll/liquid_renderer/file.rb +1 -1
- data/lib/jekyll/page.rb +15 -11
- data/lib/jekyll/plugin_manager.rb +4 -10
- data/lib/jekyll/renderer.rb +12 -19
- data/lib/jekyll/site.rb +2 -20
- data/lib/jekyll/tags/highlight.rb +5 -5
- data/lib/jekyll/tags/include.rb +13 -2
- data/lib/jekyll/url.rb +22 -12
- data/lib/jekyll/utils.rb +48 -8
- data/lib/jekyll/utils/ansi.rb +59 -0
- data/lib/jekyll/utils/platforms.rb +2 -1
- data/lib/jekyll/version.rb +1 -1
- metadata +14 -5
@@ -0,0 +1,61 @@
|
|
1
|
+
require "webrick"
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Commands
|
5
|
+
class Serve
|
6
|
+
class Servlet < WEBrick::HTTPServlet::FileHandler
|
7
|
+
DEFAULTS = {
|
8
|
+
"Cache-Control" => "private, max-age=0, proxy-revalidate, " \
|
9
|
+
"no-store, no-cache, must-revalidate"
|
10
|
+
}
|
11
|
+
|
12
|
+
def initialize(server, root, callbacks)
|
13
|
+
# So we can access them easily.
|
14
|
+
@jekyll_opts = server.config[:JekyllOptions]
|
15
|
+
set_defaults
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
# Add the ability to tap file.html the same way that Nginx does on our
|
20
|
+
# Docker images (or on Github pages.) The difference is that we might end
|
21
|
+
# up with a different preference on which comes first.
|
22
|
+
|
23
|
+
def search_file(req, res, basename)
|
24
|
+
# /file.* > /file/index.html > /file.html
|
25
|
+
super || super(req, res, "#{basename}.html")
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
|
30
|
+
def do_GET(req, res)
|
31
|
+
rtn = super
|
32
|
+
validate_and_ensure_charset(req, res)
|
33
|
+
res.header.merge!(@headers)
|
34
|
+
rtn
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
|
39
|
+
private
|
40
|
+
def validate_and_ensure_charset(req, res)
|
41
|
+
key = res.header.keys.grep(/content-type/i).first
|
42
|
+
typ = res.header[key]
|
43
|
+
|
44
|
+
unless typ =~ /;\s*charset=/
|
45
|
+
res.header[key] = "#{typ}; charset=#{@jekyll_opts["encoding"]}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
|
51
|
+
private
|
52
|
+
def set_defaults
|
53
|
+
hash_ = @jekyll_opts.fetch("webrick", {}).fetch("headers", {})
|
54
|
+
DEFAULTS.each_with_object(@headers = hash_) do |(key, val), hash|
|
55
|
+
hash[key] = val if !hash.key?(key)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/jekyll/configuration.rb
CHANGED
@@ -65,39 +65,14 @@ module Jekyll
|
|
65
65
|
|
66
66
|
'kramdown' => {
|
67
67
|
'auto_ids' => true,
|
68
|
-
'footnote_nr' => 1,
|
69
|
-
'entity_output' => 'as_char',
|
70
68
|
'toc_levels' => '1..6',
|
69
|
+
'entity_output' => 'as_char',
|
71
70
|
'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo',
|
72
|
-
'
|
73
|
-
|
74
|
-
'
|
75
|
-
'coderay_wrap' => 'div',
|
76
|
-
'coderay_line_numbers' => 'inline',
|
77
|
-
'coderay_line_number_start' => 1,
|
78
|
-
'coderay_tab_width' => 4,
|
79
|
-
'coderay_bold_every' => 10,
|
80
|
-
'coderay_css' => 'style'
|
81
|
-
}
|
71
|
+
'input' => "GFM",
|
72
|
+
'hard_wrap' => false,
|
73
|
+
'footnote_nr' => 1
|
82
74
|
}
|
83
|
-
}]
|
84
|
-
|
85
|
-
class << self
|
86
|
-
# Static: Produce a Configuration ready for use in a Site.
|
87
|
-
# It takes the input, fills in the defaults where values do not
|
88
|
-
# exist, and patches common issues including migrating options for
|
89
|
-
# backwards compatiblity. Except where a key or value is being fixed,
|
90
|
-
# the user configuration will override the defaults.
|
91
|
-
#
|
92
|
-
# user_config - a Hash or Configuration of overrides.
|
93
|
-
#
|
94
|
-
# Returns a Configuration filled with defaults and fixed for common
|
95
|
-
# problems and backwards-compatibility.
|
96
|
-
def from(user_config)
|
97
|
-
Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys).
|
98
|
-
fix_common_issues.add_default_collections
|
99
|
-
end
|
100
|
-
end
|
75
|
+
}]
|
101
76
|
|
102
77
|
# Public: Turn all keys into string
|
103
78
|
#
|
@@ -135,7 +110,7 @@ module Jekyll
|
|
135
110
|
Jekyll::External.require_with_graceful_fail('toml') unless defined?(TOML)
|
136
111
|
TOML.load_file(filename)
|
137
112
|
when /\.ya?ml/i
|
138
|
-
SafeYAML.load_file(filename)
|
113
|
+
SafeYAML.load_file(filename) || {}
|
139
114
|
else
|
140
115
|
raise ArgumentError, "No parser for '#{filename}' is available. Use a .toml or .y(a)ml file instead."
|
141
116
|
end
|
@@ -170,7 +145,7 @@ module Jekyll
|
|
170
145
|
# Returns this configuration, overridden by the values in the file
|
171
146
|
def read_config_file(file)
|
172
147
|
next_config = safe_load_file(file)
|
173
|
-
|
148
|
+
check_config_is_hash!(next_config, file)
|
174
149
|
Jekyll.logger.info "Configuration file:", file
|
175
150
|
next_config
|
176
151
|
rescue SystemCallError
|
@@ -194,7 +169,6 @@ module Jekyll
|
|
194
169
|
|
195
170
|
begin
|
196
171
|
files.each do |config_file|
|
197
|
-
next if config_file.nil? or config_file.empty?
|
198
172
|
new_config = read_config_file(config_file)
|
199
173
|
configuration = Utils.deep_merge_hashes(configuration, new_config)
|
200
174
|
end
|
@@ -254,14 +228,15 @@ module Jekyll
|
|
254
228
|
end
|
255
229
|
|
256
230
|
%w[include exclude].each do |option|
|
257
|
-
|
231
|
+
config[option] ||= []
|
232
|
+
if config[option].is_a?(String)
|
258
233
|
Jekyll::Deprecator.deprecation_message "The '#{option}' configuration option" +
|
259
234
|
" must now be specified as an array, but you specified" +
|
260
235
|
" a string. For now, we've treated the string you provided" +
|
261
236
|
" as a list of comma-separated values."
|
262
237
|
config[option] = csv_to_array(config[option])
|
263
238
|
end
|
264
|
-
config[option].map!(&:to_s)
|
239
|
+
config[option].map!(&:to_s)
|
265
240
|
end
|
266
241
|
|
267
242
|
if (config['kramdown'] || {}).key?('use_coderay')
|
@@ -296,22 +271,14 @@ module Jekyll
|
|
296
271
|
def add_default_collections
|
297
272
|
config = clone
|
298
273
|
|
299
|
-
# It defaults to `{}`, so this is only if someone sets it to null manually.
|
300
274
|
return config if config['collections'].nil?
|
301
275
|
|
302
|
-
# Ensure we have a hash.
|
303
276
|
if config['collections'].is_a?(Array)
|
304
277
|
config['collections'] = Hash[config['collections'].map{|c| [c, {}]}]
|
305
278
|
end
|
306
|
-
|
307
|
-
config['collections'] =
|
308
|
-
|
309
|
-
).tap do |collections|
|
310
|
-
collections['posts']['output'] = true
|
311
|
-
if config['permalink']
|
312
|
-
collections['posts']['permalink'] ||= style_to_permalink(config['permalink'])
|
313
|
-
end
|
314
|
-
end
|
279
|
+
config['collections']['posts'] ||= {}
|
280
|
+
config['collections']['posts']['output'] = true
|
281
|
+
config['collections']['posts']['permalink'] = style_to_permalink(config['permalink'])
|
315
282
|
|
316
283
|
config
|
317
284
|
end
|
@@ -326,6 +293,7 @@ module Jekyll
|
|
326
293
|
end
|
327
294
|
|
328
295
|
private
|
296
|
+
|
329
297
|
def style_to_permalink(permalink_style)
|
330
298
|
case permalink_style.to_sym
|
331
299
|
when :pretty
|
@@ -340,5 +308,17 @@ module Jekyll
|
|
340
308
|
permalink_style.to_s
|
341
309
|
end
|
342
310
|
end
|
311
|
+
|
312
|
+
# Private: Checks if a given config is a hash
|
313
|
+
#
|
314
|
+
# extracted_config - the value to check
|
315
|
+
# file - the file from which the config was extracted
|
316
|
+
#
|
317
|
+
# Raises an ArgumentError if given config is not a hash
|
318
|
+
def check_config_is_hash!(extracted_config, file)
|
319
|
+
unless extracted_config.is_a?(Hash)
|
320
|
+
raise ArgumentError.new("Configuration file: (INVALID) #{file}".yellow)
|
321
|
+
end
|
322
|
+
end
|
343
323
|
end
|
344
324
|
end
|
@@ -1,54 +1,59 @@
|
|
1
1
|
module Jekyll
|
2
2
|
module Converters
|
3
3
|
class Markdown < Converter
|
4
|
-
safe true
|
5
|
-
|
6
4
|
highlighter_prefix "\n"
|
7
5
|
highlighter_suffix "\n"
|
6
|
+
safe true
|
8
7
|
|
9
8
|
def setup
|
10
9
|
return if @setup
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
if allowed_custom_class?(@config['markdown'])
|
19
|
-
self.class.const_get(@config['markdown']).new(@config)
|
20
|
-
else
|
21
|
-
Jekyll.logger.error "Invalid Markdown Processor:", "#{@config['markdown']}"
|
22
|
-
Jekyll.logger.error "", "Valid options are [ #{valid_processors.join(" | ")} ]"
|
23
|
-
raise Errors::FatalException, "Invalid Markdown Processor: #{@config['markdown']}"
|
24
|
-
end
|
25
|
-
end
|
10
|
+
if (!@parser = get_processor)
|
11
|
+
Jekyll.logger.error "Invalid Markdown processor given:", @config["markdown"]
|
12
|
+
Jekyll.logger.info "", "Custom processors are not loaded in safe mode" if @config["safe"]
|
13
|
+
Jekyll.logger.error "", "Available processors are: #{valid_processors.join(", ")}"
|
14
|
+
raise Errors::FatalException, "Bailing out; invalid Markdown processor."
|
15
|
+
end
|
16
|
+
|
26
17
|
@setup = true
|
27
18
|
end
|
28
19
|
|
20
|
+
def get_processor
|
21
|
+
case @config["markdown"].downcase
|
22
|
+
when "redcarpet" then return RedcarpetParser.new(@config)
|
23
|
+
when "kramdown" then return KramdownParser.new(@config)
|
24
|
+
when "rdiscount" then return RDiscountParser.new(@config)
|
25
|
+
else
|
26
|
+
get_custom_processor
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Public: Provides you with a list of processors, the ones we
|
31
|
+
# support internally and the ones that you have provided to us (if you
|
32
|
+
# are not in safe mode.)
|
33
|
+
|
29
34
|
def valid_processors
|
30
|
-
%
|
31
|
-
rdiscount
|
32
|
-
kramdown
|
33
|
-
redcarpet
|
34
|
-
] + third_party_processors
|
35
|
+
%W(rdiscount kramdown redcarpet) + third_party_processors
|
35
36
|
end
|
36
37
|
|
38
|
+
# Public: A list of processors that you provide via plugins.
|
39
|
+
# This is really only available if you are not in safe mode, if you are
|
40
|
+
# in safe mode (re: Github) then there will be none.
|
41
|
+
|
37
42
|
def third_party_processors
|
38
|
-
self.class.constants -
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
PRIORITIES
|
43
|
-
].map(&:to_sym)
|
43
|
+
self.class.constants - \
|
44
|
+
%w[KramdownParser RDiscountParser RedcarpetParser PRIORITIES].map(
|
45
|
+
&:to_sym
|
46
|
+
)
|
44
47
|
end
|
45
48
|
|
46
49
|
def extname_list
|
47
|
-
@extname_list ||= @config['markdown_ext'].split(',').map
|
50
|
+
@extname_list ||= @config['markdown_ext'].split(',').map do |e|
|
51
|
+
".#{e.downcase}"
|
52
|
+
end
|
48
53
|
end
|
49
54
|
|
50
55
|
def matches(ext)
|
51
|
-
extname_list.include?
|
56
|
+
extname_list.include?(ext.downcase)
|
52
57
|
end
|
53
58
|
|
54
59
|
def output_ext(ext)
|
@@ -61,16 +66,26 @@ module Jekyll
|
|
61
66
|
end
|
62
67
|
|
63
68
|
private
|
69
|
+
def get_custom_processor
|
70
|
+
converter_name = @config["markdown"]
|
71
|
+
if custom_class_allowed?(converter_name)
|
72
|
+
self.class.const_get(converter_name).new(@config)
|
73
|
+
end
|
74
|
+
end
|
64
75
|
|
65
|
-
# Private: Determine whether a class name is an allowed custom
|
66
|
-
# class name
|
76
|
+
# Private: Determine whether a class name is an allowed custom
|
77
|
+
# markdown class name.
|
67
78
|
#
|
68
79
|
# parser_name - the name of the parser class
|
69
80
|
#
|
70
|
-
# Returns true if the parser name contains only alphanumeric
|
71
|
-
# and is defined within Jekyll::Converters::Markdown
|
72
|
-
|
73
|
-
|
81
|
+
# Returns true if the parser name contains only alphanumeric
|
82
|
+
# characters and is defined within Jekyll::Converters::Markdown
|
83
|
+
|
84
|
+
private
|
85
|
+
def custom_class_allowed?(parser_name)
|
86
|
+
parser_name !~ /[^A-Za-z0-9_]/ && self.class.constants.include?(
|
87
|
+
parser_name.to_sym
|
88
|
+
)
|
74
89
|
end
|
75
90
|
end
|
76
91
|
end
|
@@ -1,33 +1,86 @@
|
|
1
|
+
# Frozen-string-literal: true
|
2
|
+
# Encoding: utf-8
|
3
|
+
|
1
4
|
module Jekyll
|
2
5
|
module Converters
|
3
6
|
class Markdown
|
4
7
|
class KramdownParser
|
8
|
+
CODERAY_DEFAULTS = {
|
9
|
+
"css" => "style",
|
10
|
+
"bold_every" => 10,
|
11
|
+
"line_numbers" => "inline",
|
12
|
+
"line_number_start" => 1,
|
13
|
+
"tab_width" => 4,
|
14
|
+
"wrap" => "div"
|
15
|
+
}
|
16
|
+
|
5
17
|
def initialize(config)
|
6
|
-
|
7
|
-
@
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
18
|
+
Jekyll::External.require_with_graceful_fail "kramdown"
|
19
|
+
@main_fallback_highlighter = config["highlighter"] || "rogue"
|
20
|
+
@config = config["kramdown"] || {}
|
21
|
+
setup
|
22
|
+
end
|
23
|
+
|
24
|
+
# Setup and normalize the configuration:
|
25
|
+
# * Create Kramdown if it doesn't exist.
|
26
|
+
# * Set syntax_highlighter, detecting enable_coderay and merging highlighter if none.
|
27
|
+
# * Merge kramdown[coderay] into syntax_highlighter_opts stripping coderay_.
|
28
|
+
# * Make sure `syntax_highlighter_opts` exists.
|
29
|
+
|
30
|
+
def setup
|
31
|
+
@config["syntax_highlighter"] ||= highlighter
|
32
|
+
@config["syntax_highlighter_opts"] ||= {}
|
33
|
+
@config["coderay"] ||= {} # XXX: Legacy.
|
34
|
+
modernize_coderay_config
|
17
35
|
end
|
18
36
|
|
19
37
|
def convert(content)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
38
|
+
Kramdown::Document.new(content, @config).to_html
|
39
|
+
end
|
40
|
+
|
41
|
+
# config[kramdown][syntax_higlighter] > config[kramdown][enable_coderay] > config[highlighter]
|
42
|
+
# Where `enable_coderay` is now deprecated because Kramdown
|
43
|
+
# supports Rouge now too.
|
44
|
+
|
45
|
+
private
|
46
|
+
def highlighter
|
47
|
+
@highlighter ||= begin
|
48
|
+
if highlighter = @config["syntax_highlighter"] then highlighter
|
49
|
+
elsif @config.key?("enable_coderay") && @config["enable_coderay"]
|
50
|
+
Jekyll::Deprecator.deprecation_message "You are using 'enable_coderay', use syntax_highlighter: coderay in your configuration file."
|
51
|
+
"coderay"
|
52
|
+
else
|
53
|
+
@main_fallback_highlighter
|
25
54
|
end
|
26
55
|
end
|
56
|
+
end
|
27
57
|
|
28
|
-
|
58
|
+
private
|
59
|
+
def strip_coderay_prefix(hash)
|
60
|
+
hash.each_with_object({}) do |(key, val), hsh|
|
61
|
+
cleaned_key = key.gsub(/\Acoderay_/, "")
|
62
|
+
Jekyll::Deprecator.deprecation_message "You are using '#{key}'. Normalizing to #{cleaned_key}." if key != cleaned_key
|
63
|
+
hsh[cleaned_key] = val
|
64
|
+
end
|
29
65
|
end
|
30
66
|
|
67
|
+
# If our highlighter is CodeRay we go in to merge the CodeRay defaults
|
68
|
+
# with your "coderay" key if it's there, deprecating it in the
|
69
|
+
# process of you using it.
|
70
|
+
|
71
|
+
private
|
72
|
+
def modernize_coderay_config
|
73
|
+
if highlighter == "coderay"
|
74
|
+
Jekyll::Deprecator.deprecation_message "You are using 'kramdown.coderay' in your configuration, please use 'syntax_highlighter_opts' instead."
|
75
|
+
@config["syntax_highlighter_opts"] = begin
|
76
|
+
strip_coderay_prefix(
|
77
|
+
@config["syntax_highlighter_opts"] \
|
78
|
+
.merge(CODERAY_DEFAULTS) \
|
79
|
+
.merge(@config["coderay"])
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
31
84
|
end
|
32
85
|
end
|
33
86
|
end
|
data/lib/jekyll/convertible.rb
CHANGED
@@ -210,7 +210,8 @@ module Jekyll
|
|
210
210
|
|
211
211
|
while layout
|
212
212
|
Jekyll.logger.debug "Rendering Layout:", path
|
213
|
-
payload
|
213
|
+
payload.content = output
|
214
|
+
payload.layout = layout.data
|
214
215
|
|
215
216
|
self.output = render_liquid(layout.content,
|
216
217
|
payload,
|
@@ -244,11 +245,11 @@ module Jekyll
|
|
244
245
|
|
245
246
|
Jekyll.logger.debug "Pre-Render Hooks:", self.relative_path
|
246
247
|
Jekyll::Hooks.trigger hook_owner, :pre_render, self, payload
|
247
|
-
info = { :filters => [Jekyll::Filters], :registers => { :site => site, :page => payload
|
248
|
+
info = { :filters => [Jekyll::Filters], :registers => { :site => site, :page => payload.page } }
|
248
249
|
|
249
250
|
# render and transform content (this becomes the final content of the object)
|
250
|
-
payload
|
251
|
-
payload
|
251
|
+
payload.highlighter_prefix = converters.first.highlighter_prefix
|
252
|
+
payload.highlighter_suffix = converters.first.highlighter_suffix
|
252
253
|
|
253
254
|
if render_with_liquid?
|
254
255
|
Jekyll.logger.debug "Rendering Liquid:", self.relative_path
|