jekyll 4.1.1 → 4.2.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +150 -4
- data/README.markdown +2 -6
- data/lib/blank_template/_layouts/default.html +1 -1
- data/lib/jekyll.rb +2 -16
- data/lib/jekyll/cleaner.rb +1 -1
- data/lib/jekyll/commands/doctor.rb +19 -15
- data/lib/jekyll/commands/new_theme.rb +0 -2
- data/lib/jekyll/commands/serve.rb +3 -0
- data/lib/jekyll/configuration.rb +11 -14
- data/lib/jekyll/convertible.rb +17 -11
- data/lib/jekyll/document.rb +20 -12
- data/lib/jekyll/drops/collection_drop.rb +3 -3
- data/lib/jekyll/drops/document_drop.rb +4 -15
- data/lib/jekyll/drops/drop.rb +98 -20
- data/lib/jekyll/drops/site_drop.rb +3 -3
- data/lib/jekyll/drops/static_file_drop.rb +4 -4
- data/lib/jekyll/drops/url_drop.rb +2 -2
- data/lib/jekyll/filters.rb +6 -9
- data/lib/jekyll/filters/url_filters.rb +5 -2
- data/lib/jekyll/frontmatter_defaults.rb +2 -2
- data/lib/jekyll/hooks.rb +20 -16
- data/lib/jekyll/layout.rb +5 -0
- data/lib/jekyll/page.rb +20 -13
- data/lib/jekyll/path_manager.rb +53 -10
- data/lib/jekyll/reader.rb +11 -6
- data/lib/jekyll/readers/data_reader.rb +3 -0
- data/lib/jekyll/readers/post_reader.rb +1 -1
- data/lib/jekyll/related_posts.rb +1 -1
- data/lib/jekyll/renderer.rb +8 -4
- data/lib/jekyll/site.rb +17 -2
- data/lib/jekyll/static_file.rb +2 -2
- data/lib/jekyll/tags/include.rb +21 -27
- data/lib/jekyll/tags/link.rb +2 -1
- data/lib/jekyll/tags/post_url.rb +3 -4
- data/lib/jekyll/url.rb +8 -5
- data/lib/jekyll/utils/platforms.rb +34 -49
- data/lib/jekyll/version.rb +1 -1
- metadata +7 -7
data/lib/jekyll/convertible.rb
CHANGED
@@ -35,13 +35,13 @@ module Jekyll
|
|
35
35
|
# Returns nothing.
|
36
36
|
# rubocop:disable Metrics/AbcSize
|
37
37
|
def read_yaml(base, name, opts = {})
|
38
|
-
filename =
|
38
|
+
filename = @path || site.in_source_dir(base, name)
|
39
|
+
Jekyll.logger.debug "Reading:", relative_path
|
39
40
|
|
40
41
|
begin
|
41
|
-
self.content = File.read(
|
42
|
-
**Utils.merged_file_read_opts(site, opts))
|
42
|
+
self.content = File.read(filename, **Utils.merged_file_read_opts(site, opts))
|
43
43
|
if content =~ Document::YAML_FRONT_MATTER_REGEXP
|
44
|
-
self.content =
|
44
|
+
self.content = Regexp.last_match.post_match
|
45
45
|
self.data = SafeYAML.load(Regexp.last_match(1))
|
46
46
|
end
|
47
47
|
rescue Psych::SyntaxError => e
|
@@ -69,7 +69,7 @@ module Jekyll
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def validate_permalink!(filename)
|
72
|
-
if self.data["permalink"]
|
72
|
+
if self.data["permalink"] == ""
|
73
73
|
raise Errors::InvalidPermalinkError, "Invalid permalink in #{filename}"
|
74
74
|
end
|
75
75
|
end
|
@@ -112,12 +112,7 @@ module Jekyll
|
|
112
112
|
#
|
113
113
|
# Returns the Hash representation of this Convertible.
|
114
114
|
def to_liquid(attrs = nil)
|
115
|
-
further_data =
|
116
|
-
(attrs || self.class::ATTRIBUTES_FOR_LIQUID).each_with_object({}) do |attribute, hsh|
|
117
|
-
hsh[attribute] = send(attribute)
|
118
|
-
end
|
119
|
-
|
120
|
-
defaults = site.frontmatter_defaults.all(relative_path, type)
|
115
|
+
further_data = attribute_hash(attrs || self.class::ATTRIBUTES_FOR_LIQUID)
|
121
116
|
Utils.deep_merge_hashes defaults, Utils.deep_merge_hashes(data, further_data)
|
122
117
|
end
|
123
118
|
|
@@ -247,6 +242,17 @@ module Jekyll
|
|
247
242
|
|
248
243
|
private
|
249
244
|
|
245
|
+
def defaults
|
246
|
+
@defaults ||= site.frontmatter_defaults.all(relative_path, type)
|
247
|
+
end
|
248
|
+
|
249
|
+
def attribute_hash(attrs)
|
250
|
+
@attribute_hash ||= {}
|
251
|
+
@attribute_hash[attrs] ||= attrs.each_with_object({}) do |attribute, hsh|
|
252
|
+
hsh[attribute] = send(attribute)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
250
256
|
def no_layout?
|
251
257
|
data["layout"] == "none"
|
252
258
|
end
|
data/lib/jekyll/document.rb
CHANGED
@@ -257,14 +257,16 @@ module Jekyll
|
|
257
257
|
#
|
258
258
|
# Returns the full path to the output file of this document.
|
259
259
|
def destination(base_directory)
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
260
|
+
@destination ||= {}
|
261
|
+
@destination[base_directory] ||= begin
|
262
|
+
path = site.in_dest_dir(base_directory, URL.unescape_path(url))
|
263
|
+
if url.end_with? "/"
|
264
|
+
path = File.join(path, "index.html")
|
265
|
+
else
|
266
|
+
path << output_ext unless path.end_with? output_ext
|
267
|
+
end
|
268
|
+
path
|
266
269
|
end
|
267
|
-
path
|
268
270
|
end
|
269
271
|
|
270
272
|
# Write the generated Document file to the destination directory.
|
@@ -351,9 +353,14 @@ module Jekyll
|
|
351
353
|
# True if the document has a collection and if that collection's #write?
|
352
354
|
# method returns true, and if the site's Publisher will publish the document.
|
353
355
|
# False otherwise.
|
356
|
+
#
|
357
|
+
# rubocop:disable Naming/MemoizedInstanceVariableName
|
354
358
|
def write?
|
355
|
-
|
359
|
+
return @write_p if defined?(@write_p)
|
360
|
+
|
361
|
+
@write_p = collection&.write? && site.publisher.publish?(self)
|
356
362
|
end
|
363
|
+
# rubocop:enable Naming/MemoizedInstanceVariableName
|
357
364
|
|
358
365
|
# The Document excerpt_separator, from the YAML Front-Matter or site
|
359
366
|
# default excerpt_separator value
|
@@ -452,7 +459,10 @@ module Jekyll
|
|
452
459
|
def merge_categories!(other)
|
453
460
|
if other.key?("categories") && !other["categories"].nil?
|
454
461
|
other["categories"] = other["categories"].split if other["categories"].is_a?(String)
|
455
|
-
|
462
|
+
|
463
|
+
if data["categories"].is_a?(Array)
|
464
|
+
other["categories"] = data["categories"] | other["categories"]
|
465
|
+
end
|
456
466
|
end
|
457
467
|
end
|
458
468
|
|
@@ -473,7 +483,7 @@ module Jekyll
|
|
473
483
|
def read_content(**opts)
|
474
484
|
self.content = File.read(path, **Utils.merged_file_read_opts(site, opts))
|
475
485
|
if content =~ YAML_FRONT_MATTER_REGEXP
|
476
|
-
self.content =
|
486
|
+
self.content = Regexp.last_match.post_match
|
477
487
|
data_file = SafeYAML.load(Regexp.last_match(1))
|
478
488
|
merge_data!(data_file, :source => "YAML front matter") if data_file
|
479
489
|
end
|
@@ -498,7 +508,6 @@ module Jekyll
|
|
498
508
|
end
|
499
509
|
end
|
500
510
|
|
501
|
-
# rubocop:disable Metrics/AbcSize
|
502
511
|
def populate_title
|
503
512
|
if relative_path =~ DATE_FILENAME_MATCHER
|
504
513
|
date, slug, ext = Regexp.last_match.captures
|
@@ -521,7 +530,6 @@ module Jekyll
|
|
521
530
|
data["slug"] ||= slug
|
522
531
|
data["ext"] ||= ext
|
523
532
|
end
|
524
|
-
# rubocop:enable Metrics/AbcSize
|
525
533
|
|
526
534
|
def modify_date(date)
|
527
535
|
if !data["date"] || data["date"].to_i == site.time.to_i
|
@@ -7,10 +7,10 @@ module Jekyll
|
|
7
7
|
|
8
8
|
mutable false
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
delegate_method_as :write?, :output
|
11
|
+
delegate_methods :label, :docs, :files, :directory, :relative_directory
|
12
12
|
|
13
|
-
private
|
13
|
+
private delegate_method_as :metadata, :fallback_data
|
14
14
|
|
15
15
|
def to_s
|
16
16
|
docs.to_s
|
@@ -11,10 +11,11 @@ module Jekyll
|
|
11
11
|
|
12
12
|
mutable false
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
delegate_method_as :relative_path, :path
|
15
|
+
private delegate_method_as :data, :fallback_data
|
16
16
|
|
17
|
-
|
17
|
+
delegate_methods :id, :output, :content, :to_s, :relative_path, :url, :date
|
18
|
+
data_delegators "title", "categories", "tags"
|
18
19
|
|
19
20
|
def collection
|
20
21
|
@obj.collection.label
|
@@ -64,18 +65,6 @@ module Jekyll
|
|
64
65
|
result[key] = doc[key] unless NESTED_OBJECT_FIELD_BLACKLIST.include?(key)
|
65
66
|
end
|
66
67
|
end
|
67
|
-
|
68
|
-
def title
|
69
|
-
@obj.data["title"]
|
70
|
-
end
|
71
|
-
|
72
|
-
def categories
|
73
|
-
@obj.data["categories"]
|
74
|
-
end
|
75
|
-
|
76
|
-
def tags
|
77
|
-
@obj.data["tags"]
|
78
|
-
end
|
79
68
|
end
|
80
69
|
end
|
81
70
|
end
|
data/lib/jekyll/drops/drop.rb
CHANGED
@@ -6,20 +6,101 @@ module Jekyll
|
|
6
6
|
include Enumerable
|
7
7
|
|
8
8
|
NON_CONTENT_METHODS = [:fallback_data, :collapse_document].freeze
|
9
|
+
NON_CONTENT_METHOD_NAMES = NON_CONTENT_METHODS.map(&:to_s).freeze
|
10
|
+
private_constant :NON_CONTENT_METHOD_NAMES
|
9
11
|
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
# A private stash to avoid repeatedly generating the setter method name string for
|
13
|
+
# a call to `Drops::Drop#[]=`.
|
14
|
+
# The keys of the stash below have a very high probability of being called upon during
|
15
|
+
# the course of various `Jekyll::Renderer#run` calls.
|
16
|
+
SETTER_KEYS_STASH = {
|
17
|
+
"content" => "content=",
|
18
|
+
"layout" => "layout=",
|
19
|
+
"page" => "page=",
|
20
|
+
"paginator" => "paginator=",
|
21
|
+
"highlighter_prefix" => "highlighter_prefix=",
|
22
|
+
"highlighter_suffix" => "highlighter_suffix=",
|
23
|
+
}.freeze
|
24
|
+
private_constant :SETTER_KEYS_STASH
|
25
|
+
|
26
|
+
class << self
|
27
|
+
# Get or set whether the drop class is mutable.
|
28
|
+
# Mutability determines whether or not pre-defined fields may be
|
29
|
+
# overwritten.
|
30
|
+
#
|
31
|
+
# is_mutable - Boolean set mutability of the class (default: nil)
|
32
|
+
#
|
33
|
+
# Returns the mutability of the class
|
34
|
+
def mutable(is_mutable = nil)
|
35
|
+
@is_mutable = is_mutable || false
|
36
|
+
end
|
37
|
+
|
38
|
+
def mutable?
|
39
|
+
@is_mutable
|
40
|
+
end
|
41
|
+
|
42
|
+
# public delegation helper methods that calls onto Drop's instance
|
43
|
+
# variable `@obj`.
|
44
|
+
|
45
|
+
# Generate private Drop instance_methods for each symbol in the given list.
|
46
|
+
#
|
47
|
+
# Returns nothing.
|
48
|
+
def private_delegate_methods(*symbols)
|
49
|
+
symbols.each { |symbol| private delegate_method(symbol) }
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
# Generate public Drop instance_methods for each symbol in the given list.
|
54
|
+
#
|
55
|
+
# Returns nothing.
|
56
|
+
def delegate_methods(*symbols)
|
57
|
+
symbols.each { |symbol| delegate_method(symbol) }
|
58
|
+
nil
|
59
|
+
end
|
20
60
|
|
21
|
-
|
22
|
-
|
61
|
+
# Generate public Drop instance_method for given symbol that calls `@obj.<sym>`.
|
62
|
+
#
|
63
|
+
# Returns delegated method symbol.
|
64
|
+
def delegate_method(symbol)
|
65
|
+
define_method(symbol) { @obj.send(symbol) }
|
66
|
+
end
|
67
|
+
|
68
|
+
# Generate public Drop instance_method named `delegate` that calls `@obj.<original>`.
|
69
|
+
#
|
70
|
+
# Returns delegated method symbol.
|
71
|
+
def delegate_method_as(original, delegate)
|
72
|
+
define_method(delegate) { @obj.send(original) }
|
73
|
+
end
|
74
|
+
|
75
|
+
# Generate public Drop instance_methods for each string entry in the given list.
|
76
|
+
# The generated method(s) access(es) `@obj`'s data hash.
|
77
|
+
#
|
78
|
+
# Returns nothing.
|
79
|
+
def data_delegators(*strings)
|
80
|
+
strings.each do |key|
|
81
|
+
data_delegator(key) if key.is_a?(String)
|
82
|
+
end
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
# Generate public Drop instance_methods for given string `key`.
|
87
|
+
# The generated method access(es) `@obj`'s data hash.
|
88
|
+
#
|
89
|
+
# Returns method symbol.
|
90
|
+
def data_delegator(key)
|
91
|
+
define_method(key.to_sym) { @obj.data[key] }
|
92
|
+
end
|
93
|
+
|
94
|
+
# Array of stringified instance methods that do not end with the assignment operator.
|
95
|
+
#
|
96
|
+
# (<klass>.instance_methods always generates a new Array object so it can be mutated)
|
97
|
+
#
|
98
|
+
# Returns array of strings.
|
99
|
+
def getter_method_names
|
100
|
+
@getter_method_names ||= instance_methods.map!(&:to_s).tap do |list|
|
101
|
+
list.reject! { |item| item.end_with?("=") }
|
102
|
+
end
|
103
|
+
end
|
23
104
|
end
|
24
105
|
|
25
106
|
# Create a new Drop
|
@@ -65,7 +146,7 @@ module Jekyll
|
|
65
146
|
# and the key matches a method in which case it raises a
|
66
147
|
# DropMutationException.
|
67
148
|
def []=(key, val)
|
68
|
-
setter = "#{key}="
|
149
|
+
setter = SETTER_KEYS_STASH[key] || "#{key}="
|
69
150
|
if respond_to?(setter)
|
70
151
|
public_send(setter, val)
|
71
152
|
elsif respond_to?(key.to_s)
|
@@ -84,13 +165,10 @@ module Jekyll
|
|
84
165
|
#
|
85
166
|
# Returns an Array of strings which represent method-specific keys.
|
86
167
|
def content_methods
|
87
|
-
@content_methods ||=
|
88
|
-
self.class.
|
89
|
-
- Jekyll::Drops::Drop.
|
90
|
-
-
|
91
|
-
).map(&:to_s).reject do |method|
|
92
|
-
method.end_with?("=")
|
93
|
-
end
|
168
|
+
@content_methods ||= \
|
169
|
+
self.class.getter_method_names \
|
170
|
+
- Jekyll::Drops::Drop.getter_method_names \
|
171
|
+
- NON_CONTENT_METHOD_NAMES
|
94
172
|
end
|
95
173
|
|
96
174
|
# Check if key exists in Drop
|
@@ -7,10 +7,10 @@ module Jekyll
|
|
7
7
|
|
8
8
|
mutable false
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
delegate_method_as :site_data, :data
|
11
|
+
delegate_methods :time, :pages, :static_files, :tags, :categories
|
12
12
|
|
13
|
-
private
|
13
|
+
private delegate_method_as :config, :fallback_data
|
14
14
|
|
15
15
|
def [](key)
|
16
16
|
if key != "posts" && @obj.collections.key?(key)
|
@@ -4,11 +4,11 @@ module Jekyll
|
|
4
4
|
module Drops
|
5
5
|
class StaticFileDrop < Drop
|
6
6
|
extend Forwardable
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
delegate_methods :name, :extname, :modified_time, :basename
|
8
|
+
delegate_method_as :relative_path, :path
|
9
|
+
delegate_method_as :type, :collection
|
10
10
|
|
11
|
-
private
|
11
|
+
private delegate_method_as :data, :fallback_data
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -7,8 +7,8 @@ module Jekyll
|
|
7
7
|
|
8
8
|
mutable false
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
delegate_method :output_ext
|
11
|
+
delegate_method_as :cleaned_relative_path, :path
|
12
12
|
|
13
13
|
def collection
|
14
14
|
@obj.collection.label
|
data/lib/jekyll/filters.rb
CHANGED
@@ -113,7 +113,7 @@ module Jekyll
|
|
113
113
|
#
|
114
114
|
# Returns the formatted String
|
115
115
|
def normalize_whitespace(input)
|
116
|
-
input.to_s.gsub(%r!\s+!, " ").strip
|
116
|
+
input.to_s.gsub(%r!\s+!, " ").tap(&:strip!)
|
117
117
|
end
|
118
118
|
|
119
119
|
# Count the number of words in the input string.
|
@@ -307,9 +307,10 @@ module Jekyll
|
|
307
307
|
if property.nil?
|
308
308
|
input.sort
|
309
309
|
else
|
310
|
-
|
310
|
+
case nils
|
311
|
+
when "first"
|
311
312
|
order = - 1
|
312
|
-
|
313
|
+
when "last"
|
313
314
|
order = + 1
|
314
315
|
else
|
315
316
|
raise ArgumentError, "Invalid nils order: " \
|
@@ -399,7 +400,6 @@ module Jekyll
|
|
399
400
|
|
400
401
|
# `where` filter helper
|
401
402
|
#
|
402
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
403
403
|
def compare_property_vs_target(property, target)
|
404
404
|
case target
|
405
405
|
when NilClass
|
@@ -421,10 +421,8 @@ module Jekyll
|
|
421
421
|
false
|
422
422
|
end
|
423
423
|
|
424
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
425
|
-
|
426
424
|
def item_property(item, property)
|
427
|
-
@item_property_cache ||= {}
|
425
|
+
@item_property_cache ||= @context.registers[:site].filter_cache[:item_property] ||= {}
|
428
426
|
@item_property_cache[property] ||= {}
|
429
427
|
@item_property_cache[property][item] ||= begin
|
430
428
|
property = property.to_s
|
@@ -464,8 +462,7 @@ module Jekyll
|
|
464
462
|
def as_liquid(item)
|
465
463
|
case item
|
466
464
|
when Hash
|
467
|
-
|
468
|
-
Hash[pairs]
|
465
|
+
item.each_with_object({}) { |(k, v), result| result[as_liquid(k)] = as_liquid(v) }
|
469
466
|
when Array
|
470
467
|
item.map { |i| as_liquid(i) }
|
471
468
|
else
|
@@ -76,13 +76,16 @@ module Jekyll
|
|
76
76
|
|
77
77
|
parts = [sanitized_baseurl, input]
|
78
78
|
Addressable::URI.parse(
|
79
|
-
parts.
|
79
|
+
parts.map! { |part| ensure_leading_slash(part.to_s) }.join
|
80
80
|
).normalize.to_s
|
81
81
|
end
|
82
82
|
|
83
83
|
def sanitized_baseurl
|
84
84
|
site = @context.registers[:site]
|
85
|
-
site.config["baseurl"]
|
85
|
+
baseurl = site.config["baseurl"]
|
86
|
+
return "" if baseurl.nil?
|
87
|
+
|
88
|
+
baseurl.to_s.chomp("/")
|
86
89
|
end
|
87
90
|
|
88
91
|
def ensure_leading_slash(input)
|
@@ -157,7 +157,7 @@ module Jekyll
|
|
157
157
|
# Returns true if either of the above conditions are satisfied,
|
158
158
|
# otherwise returns false
|
159
159
|
def applies_type?(scope, type)
|
160
|
-
!scope.key?("type") || scope["type"].
|
160
|
+
!scope.key?("type") || type&.to_sym.eql?(scope["type"].to_sym)
|
161
161
|
end
|
162
162
|
|
163
163
|
# Checks if a given set of default values is valid
|
@@ -223,7 +223,7 @@ module Jekyll
|
|
223
223
|
Jekyll.logger.warn set.to_s
|
224
224
|
nil
|
225
225
|
end
|
226
|
-
end.compact
|
226
|
+
end.tap(&:compact!)
|
227
227
|
end
|
228
228
|
|
229
229
|
# Sanitizes the given path by removing a leading slash
|