jekyll 3.6.3 → 3.7.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -9
- data/LICENSE +1 -1
- data/README.markdown +1 -1
- data/lib/jekyll.rb +3 -0
- data/lib/jekyll/cleaner.rb +3 -1
- data/lib/jekyll/collection.rb +7 -3
- data/lib/jekyll/commands/clean.rb +1 -1
- data/lib/jekyll/commands/doctor.rb +3 -1
- data/lib/jekyll/commands/new.rb +5 -2
- data/lib/jekyll/commands/serve.rb +183 -41
- data/lib/jekyll/commands/serve/live_reload_reactor.rb +127 -0
- data/lib/jekyll/commands/serve/livereload_assets/livereload.js +1183 -0
- data/lib/jekyll/commands/serve/servlet.rb +142 -1
- data/lib/jekyll/commands/serve/websockets.rb +80 -0
- data/lib/jekyll/configuration.rb +9 -17
- data/lib/jekyll/converters/markdown.rb +1 -1
- data/lib/jekyll/converters/markdown/kramdown_parser.rb +8 -2
- data/lib/jekyll/converters/smartypants.rb +14 -2
- data/lib/jekyll/convertible.rb +10 -4
- data/lib/jekyll/document.rb +2 -2
- data/lib/jekyll/entry_filter.rb +3 -6
- data/lib/jekyll/filters/url_filters.rb +6 -1
- data/lib/jekyll/frontmatter_defaults.rb +18 -3
- data/lib/jekyll/hooks.rb +3 -0
- data/lib/jekyll/liquid_renderer.rb +8 -6
- data/lib/jekyll/page.rb +1 -1
- data/lib/jekyll/page_without_a_file.rb +18 -0
- data/lib/jekyll/regenerator.rb +1 -1
- data/lib/jekyll/renderer.rb +2 -2
- data/lib/jekyll/site.rb +1 -3
- data/lib/jekyll/tags/highlight.rb +2 -2
- data/lib/jekyll/tags/include.rb +1 -1
- data/lib/jekyll/tags/post_url.rb +1 -1
- data/lib/jekyll/theme.rb +3 -2
- data/lib/jekyll/theme_builder.rb +8 -8
- data/lib/jekyll/utils.rb +41 -22
- data/lib/jekyll/utils/ansi.rb +0 -2
- data/lib/jekyll/utils/internet.rb +39 -0
- data/lib/jekyll/utils/thread_event.rb +35 -0
- data/lib/jekyll/version.rb +1 -1
- metadata +41 -7
@@ -12,6 +12,7 @@ module Jekyll
|
|
12
12
|
# Returns the absolute URL as a String.
|
13
13
|
def absolute_url(input)
|
14
14
|
return if input.nil?
|
15
|
+
input = input.url if input.respond_to?(:url)
|
15
16
|
return input if Addressable::URI.parse(input.to_s).absolute?
|
16
17
|
site = @context.registers[:site]
|
17
18
|
return relative_url(input) if site.config["url"].nil?
|
@@ -20,13 +21,17 @@ module Jekyll
|
|
20
21
|
).normalize.to_s
|
21
22
|
end
|
22
23
|
|
23
|
-
# Produces a URL relative to the domain root based on site.baseurl
|
24
|
+
# Produces a URL relative to the domain root based on site.baseurl
|
25
|
+
# unless it is already an absolute url with an authority (host).
|
24
26
|
#
|
25
27
|
# input - the URL to make relative to the domain root
|
26
28
|
#
|
27
29
|
# Returns a URL relative to the domain root as a String.
|
28
30
|
def relative_url(input)
|
29
31
|
return if input.nil?
|
32
|
+
input = input.url if input.respond_to?(:url)
|
33
|
+
return input if Addressable::URI.parse(input.to_s).absolute?
|
34
|
+
|
30
35
|
parts = [sanitized_baseurl, input]
|
31
36
|
Addressable::URI.parse(
|
32
37
|
parts.compact.map { |part| ensure_leading_slash(part.to_s) }.join
|
@@ -100,12 +100,27 @@ module Jekyll
|
|
100
100
|
def applies_path?(scope, path)
|
101
101
|
return true if !scope.key?("path") || scope["path"].empty?
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
103
|
+
sanitized_path = Pathname.new(sanitize_path(path))
|
104
|
+
|
105
|
+
site_path = Pathname.new(@site.source)
|
106
|
+
rel_scope_path = Pathname.new(scope["path"])
|
107
|
+
abs_scope_path = File.join(@site.source, rel_scope_path)
|
108
|
+
Dir.glob(abs_scope_path).each do |scope_path|
|
109
|
+
scope_path = Pathname.new(scope_path).relative_path_from site_path
|
110
|
+
return true if path_is_subpath?(sanitized_path, scope_path)
|
111
|
+
end
|
112
|
+
|
113
|
+
path_is_subpath?(sanitized_path, rel_scope_path)
|
114
|
+
end
|
115
|
+
|
116
|
+
def path_is_subpath?(path, parent_path)
|
117
|
+
path.ascend do |ascended_path|
|
118
|
+
if ascended_path.to_s == parent_path.to_s
|
106
119
|
return true
|
107
120
|
end
|
108
121
|
end
|
122
|
+
|
123
|
+
false
|
109
124
|
end
|
110
125
|
|
111
126
|
# Determines whether the scope applies to type.
|
data/lib/jekyll/hooks.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require_relative "liquid_renderer/file"
|
4
|
+
require_relative "liquid_renderer/table"
|
5
5
|
|
6
6
|
module Jekyll
|
7
7
|
class LiquidRenderer
|
@@ -22,19 +22,16 @@ module Jekyll
|
|
22
22
|
)
|
23
23
|
|
24
24
|
LiquidRenderer::File.new(self, filename).tap do
|
25
|
-
@stats[filename] ||=
|
26
|
-
@stats[filename][:count] ||= 0
|
25
|
+
@stats[filename] ||= new_profile_hash
|
27
26
|
@stats[filename][:count] += 1
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
30
|
def increment_bytes(filename, bytes)
|
32
|
-
@stats[filename][:bytes] ||= 0
|
33
31
|
@stats[filename][:bytes] += bytes
|
34
32
|
end
|
35
33
|
|
36
34
|
def increment_time(filename, time)
|
37
|
-
@stats[filename][:time] ||= 0.0
|
38
35
|
@stats[filename][:time] += time
|
39
36
|
end
|
40
37
|
|
@@ -45,5 +42,10 @@ module Jekyll
|
|
45
42
|
def self.format_error(e, path)
|
46
43
|
"#{e.message} in #{path}"
|
47
44
|
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def new_profile_hash
|
48
|
+
Hash.new { |hash, key| hash[key] = 0 }
|
49
|
+
end
|
48
50
|
end
|
49
51
|
end
|
data/lib/jekyll/page.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
# A Jekyll::Page subclass to handle processing files without reading it to
|
5
|
+
# determine the page-data and page-content based on Front Matter delimiters.
|
6
|
+
#
|
7
|
+
# The class instance is basically just a bare-bones entity with just
|
8
|
+
# attributes "dir", "name", "path", "url" defined on it.
|
9
|
+
class PageWithoutAFile < Page
|
10
|
+
def read_yaml(*)
|
11
|
+
@data ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def inspect
|
15
|
+
"#<Jekyll:PageWithoutAFile @name=#{name.inspect}>"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/jekyll/regenerator.rb
CHANGED
data/lib/jekyll/renderer.rb
CHANGED
@@ -96,7 +96,7 @@ module Jekyll
|
|
96
96
|
converters.reduce(content) do |output, converter|
|
97
97
|
begin
|
98
98
|
converter.convert output
|
99
|
-
rescue => e
|
99
|
+
rescue StandardError => e
|
100
100
|
Jekyll.logger.error "Conversion error:",
|
101
101
|
"#{converter.class} encountered an error while "\
|
102
102
|
"converting '#{document.relative_path}':"
|
@@ -198,7 +198,7 @@ module Jekyll
|
|
198
198
|
return unless document.write?
|
199
199
|
site.regenerator.add_dependency(
|
200
200
|
site.in_source_dir(document.path),
|
201
|
-
|
201
|
+
layout.path
|
202
202
|
)
|
203
203
|
end
|
204
204
|
|
data/lib/jekyll/site.rb
CHANGED
@@ -122,10 +122,8 @@ module Jekyll
|
|
122
122
|
dest_pathname = Pathname.new(dest)
|
123
123
|
Pathname.new(source).ascend do |path|
|
124
124
|
if path == dest_pathname
|
125
|
-
raise
|
126
|
-
Errors::FatalException,
|
125
|
+
raise Errors::FatalException,
|
127
126
|
"Destination directory cannot be or contain the Source directory."
|
128
|
-
)
|
129
127
|
end
|
130
128
|
end
|
131
129
|
end
|
@@ -86,7 +86,7 @@ MSG
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def render_pygments(code, is_safe)
|
89
|
-
Jekyll::External.require_with_graceful_fail("pygments")
|
89
|
+
Jekyll::External.require_with_graceful_fail("pygments") unless defined?(Pygments)
|
90
90
|
|
91
91
|
highlighted_code = Pygments.highlight(
|
92
92
|
code,
|
@@ -118,7 +118,7 @@ MSG
|
|
118
118
|
:gutter_class => "gutter",
|
119
119
|
:code_class => "code"
|
120
120
|
)
|
121
|
-
lexer = Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText
|
121
|
+
lexer = ::Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText
|
122
122
|
formatter.format(lexer.lex(code))
|
123
123
|
end
|
124
124
|
|
data/lib/jekyll/tags/include.rb
CHANGED
data/lib/jekyll/tags/post_url.rb
CHANGED
data/lib/jekyll/theme.rb
CHANGED
@@ -16,7 +16,8 @@ module Jekyll
|
|
16
16
|
# Otherwise, Jekyll.sanitized path with prepend the unresolved root
|
17
17
|
@root ||= File.realpath(gemspec.full_gem_path)
|
18
18
|
rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP
|
19
|
-
|
19
|
+
raise "Path #{gemspec.full_gem_path} does not exist, is not accessible "\
|
20
|
+
"or includes a symbolic link loop"
|
20
21
|
end
|
21
22
|
|
22
23
|
def includes_path
|
@@ -37,7 +38,7 @@ module Jekyll
|
|
37
38
|
|
38
39
|
def configure_sass
|
39
40
|
return unless sass_path
|
40
|
-
|
41
|
+
Jekyll::External.require_with_graceful_fail "sass"
|
41
42
|
Sass.load_paths << sass_path
|
42
43
|
end
|
43
44
|
|
data/lib/jekyll/theme_builder.rb
CHANGED
@@ -21,6 +21,14 @@ class Jekyll::ThemeBuilder
|
|
21
21
|
initialize_git_repo
|
22
22
|
end
|
23
23
|
|
24
|
+
def user_name
|
25
|
+
@user_name ||= `git config user.name`.chomp
|
26
|
+
end
|
27
|
+
|
28
|
+
def user_email
|
29
|
+
@user_email ||= `git config user.email`.chomp
|
30
|
+
end
|
31
|
+
|
24
32
|
private
|
25
33
|
|
26
34
|
def root
|
@@ -85,14 +93,6 @@ class Jekyll::ThemeBuilder
|
|
85
93
|
write_file(".gitignore", template("gitignore"))
|
86
94
|
end
|
87
95
|
|
88
|
-
def user_name
|
89
|
-
@user_name ||= `git config user.name`.chomp
|
90
|
-
end
|
91
|
-
|
92
|
-
def user_email
|
93
|
-
@user_email ||= `git config user.email`.chomp
|
94
|
-
end
|
95
|
-
|
96
96
|
class ERBRenderer
|
97
97
|
extend Forwardable
|
98
98
|
|
data/lib/jekyll/utils.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module Jekyll
|
@@ -6,12 +5,14 @@ module Jekyll
|
|
6
5
|
extend self
|
7
6
|
autoload :Ansi, "jekyll/utils/ansi"
|
8
7
|
autoload :Exec, "jekyll/utils/exec"
|
8
|
+
autoload :Internet, "jekyll/utils/internet"
|
9
9
|
autoload :Platforms, "jekyll/utils/platforms"
|
10
10
|
autoload :Rouge, "jekyll/utils/rouge"
|
11
|
+
autoload :ThreadEvent, "jekyll/utils/thread_event"
|
11
12
|
autoload :WinTZ, "jekyll/utils/win_tz"
|
12
13
|
|
13
14
|
# Constants for use in #slugify
|
14
|
-
SLUGIFY_MODES = %w(raw default pretty ascii).freeze
|
15
|
+
SLUGIFY_MODES = %w(raw default pretty ascii latin).freeze
|
15
16
|
SLUGIFY_RAW_REGEXP = Regexp.new('\\s+').freeze
|
16
17
|
SLUGIFY_DEFAULT_REGEXP = Regexp.new("[^[:alnum:]]+").freeze
|
17
18
|
SLUGIFY_PRETTY_REGEXP = Regexp.new("[^[:alnum:]._~!$&'()+,;=@]+").freeze
|
@@ -169,6 +170,10 @@ module Jekyll
|
|
169
170
|
# When mode is "ascii", some everything else except ASCII characters
|
170
171
|
# a-z (lowercase), A-Z (uppercase) and 0-9 (numbers) are not replaced with hyphen.
|
171
172
|
#
|
173
|
+
# When mode is "latin", the input string is first preprocessed so that
|
174
|
+
# any letters with accents are replaced with the plain letter. Afterwards,
|
175
|
+
# it follows the "default" mode of operation.
|
176
|
+
#
|
172
177
|
# If cased is true, all uppercase letters in the result string are
|
173
178
|
# replaced with their lowercase counterparts.
|
174
179
|
#
|
@@ -183,7 +188,10 @@ module Jekyll
|
|
183
188
|
# # => "The-_config.yml file"
|
184
189
|
#
|
185
190
|
# slugify("The _config.yml file", "ascii")
|
186
|
-
# # => "the-config
|
191
|
+
# # => "the-config-yml-file"
|
192
|
+
#
|
193
|
+
# slugify("The _config.yml file", "latin")
|
194
|
+
# # => "the-config-yml-file"
|
187
195
|
#
|
188
196
|
# Returns the slugified string.
|
189
197
|
def slugify(string, mode: nil, cased: false)
|
@@ -194,26 +202,10 @@ module Jekyll
|
|
194
202
|
return cased ? string : string.downcase
|
195
203
|
end
|
196
204
|
|
197
|
-
#
|
198
|
-
|
199
|
-
case mode
|
200
|
-
when "raw"
|
201
|
-
SLUGIFY_RAW_REGEXP
|
202
|
-
when "default"
|
203
|
-
SLUGIFY_DEFAULT_REGEXP
|
204
|
-
when "pretty"
|
205
|
-
# "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL
|
206
|
-
# and is allowed in both extN and NTFS.
|
207
|
-
SLUGIFY_PRETTY_REGEXP
|
208
|
-
when "ascii"
|
209
|
-
# For web servers not being able to handle Unicode, the safe
|
210
|
-
# method is to ditch anything else but latin letters and numeric
|
211
|
-
# digits.
|
212
|
-
SLUGIFY_ASCII_REGEXP
|
213
|
-
end
|
205
|
+
# Drop accent marks from latin characters. Everything else turns to ?
|
206
|
+
string = ::I18n.transliterate(string) if mode == "latin"
|
214
207
|
|
215
|
-
|
216
|
-
slug = string.gsub(re, "-")
|
208
|
+
slug = replace_character_sequence_with_hyphen(string, :mode => mode)
|
217
209
|
|
218
210
|
# Remove leading/trailing hyphen
|
219
211
|
slug.gsub!(%r!^\-|\-$!i, "")
|
@@ -336,5 +328,32 @@ module Jekyll
|
|
336
328
|
target[key] = val.dup if val.frozen? && duplicable?(val)
|
337
329
|
end
|
338
330
|
end
|
331
|
+
|
332
|
+
# Replace each character sequence with a hyphen.
|
333
|
+
#
|
334
|
+
# See Utils#slugify for a description of the character sequence specified
|
335
|
+
# by each mode.
|
336
|
+
private
|
337
|
+
def replace_character_sequence_with_hyphen(string, mode: "default")
|
338
|
+
replaceable_char =
|
339
|
+
case mode
|
340
|
+
when "raw"
|
341
|
+
SLUGIFY_RAW_REGEXP
|
342
|
+
when "pretty"
|
343
|
+
# "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL
|
344
|
+
# and is allowed in both extN and NTFS.
|
345
|
+
SLUGIFY_PRETTY_REGEXP
|
346
|
+
when "ascii"
|
347
|
+
# For web servers not being able to handle Unicode, the safe
|
348
|
+
# method is to ditch anything else but latin letters and numeric
|
349
|
+
# digits.
|
350
|
+
SLUGIFY_ASCII_REGEXP
|
351
|
+
else
|
352
|
+
SLUGIFY_DEFAULT_REGEXP
|
353
|
+
end
|
354
|
+
|
355
|
+
# Strip according to the mode
|
356
|
+
string.gsub(replaceable_char, "-")
|
357
|
+
end
|
339
358
|
end
|
340
359
|
end
|
data/lib/jekyll/utils/ansi.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Utils
|
5
|
+
module Internet
|
6
|
+
|
7
|
+
# Public: Determine whether the present device has a connection to
|
8
|
+
# the Internet. This allows plugin writers which require the outside
|
9
|
+
# world to have a neat fallback mechanism for offline building.
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
# if Internet.connected?
|
13
|
+
# Typhoeus.get("https://pages.github.com/versions.json")
|
14
|
+
# else
|
15
|
+
# Jekyll.logger.warn "Warning:", "Version check has been disabled."
|
16
|
+
# Jekyll.logger.warn "", "Connect to the Internet to enable it."
|
17
|
+
# nil
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# Returns true if a DNS call can successfully be made, or false if not.
|
21
|
+
module_function
|
22
|
+
def connected?
|
23
|
+
!dns("example.com").nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
module_function
|
28
|
+
def dns(domain)
|
29
|
+
require "resolv"
|
30
|
+
Resolv::DNS.open do |resolver|
|
31
|
+
resolver.getaddress(domain)
|
32
|
+
end
|
33
|
+
rescue Resolv::ResolvError, Resolv::ResolvTimeout
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thread"
|
4
|
+
|
5
|
+
module Jekyll
|
6
|
+
module Utils
|
7
|
+
# Based on the pattern and code from
|
8
|
+
# https://emptysqua.re/blog/an-event-synchronization-primitive-for-ruby/
|
9
|
+
class ThreadEvent
|
10
|
+
attr_reader :flag
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@lock = Mutex.new
|
14
|
+
@cond = ConditionVariable.new
|
15
|
+
@flag = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def set
|
19
|
+
@lock.synchronize do
|
20
|
+
yield if block_given?
|
21
|
+
@flag = true
|
22
|
+
@cond.broadcast
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def wait
|
27
|
+
@lock.synchronize do
|
28
|
+
unless @flag
|
29
|
+
@cond.wait(@lock)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|