jekyll 4.0.1 → 4.1.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 +48 -19
- data/lib/jekyll.rb +3 -0
- data/lib/jekyll/collection.rb +1 -1
- data/lib/jekyll/command.rb +4 -2
- data/lib/jekyll/commands/new.rb +2 -2
- data/lib/jekyll/commands/serve.rb +9 -1
- data/lib/jekyll/configuration.rb +1 -1
- data/lib/jekyll/converters/identity.rb +2 -2
- data/lib/jekyll/converters/markdown/kramdown_parser.rb +70 -1
- data/lib/jekyll/convertible.rb +15 -15
- data/lib/jekyll/document.rb +18 -4
- data/lib/jekyll/drops/document_drop.rb +12 -0
- data/lib/jekyll/drops/page_drop.rb +18 -0
- data/lib/jekyll/drops/url_drop.rb +8 -0
- data/lib/jekyll/entry_filter.rb +19 -6
- data/lib/jekyll/excerpt.rb +1 -1
- data/lib/jekyll/filters.rb +99 -14
- data/lib/jekyll/filters/url_filters.rb +41 -14
- data/lib/jekyll/frontmatter_defaults.rb +12 -17
- data/lib/jekyll/hooks.rb +2 -5
- data/lib/jekyll/inclusion.rb +32 -0
- data/lib/jekyll/liquid_renderer.rb +18 -15
- data/lib/jekyll/liquid_renderer/table.rb +1 -21
- data/lib/jekyll/page.rb +43 -0
- data/lib/jekyll/page_excerpt.rb +26 -0
- data/lib/jekyll/profiler.rb +58 -0
- data/lib/jekyll/readers/collection_reader.rb +1 -0
- data/lib/jekyll/readers/data_reader.rb +1 -0
- data/lib/jekyll/readers/layout_reader.rb +1 -0
- data/lib/jekyll/readers/page_reader.rb +1 -0
- data/lib/jekyll/readers/post_reader.rb +1 -0
- data/lib/jekyll/readers/static_file_reader.rb +1 -0
- data/lib/jekyll/readers/theme_assets_reader.rb +1 -0
- data/lib/jekyll/renderer.rb +9 -15
- data/lib/jekyll/site.rb +14 -5
- data/lib/jekyll/static_file.rb +14 -9
- data/lib/jekyll/tags/include.rb +58 -3
- data/lib/jekyll/theme.rb +6 -0
- data/lib/jekyll/utils.rb +4 -4
- data/lib/jekyll/utils/win_tz.rb +1 -1
- data/lib/jekyll/version.rb +1 -1
- data/lib/theme_template/theme.gemspec.erb +1 -4
- metadata +14 -31
data/lib/jekyll/hooks.rb
CHANGED
@@ -91,11 +91,8 @@ module Jekyll
|
|
91
91
|
# interface for Jekyll core components to trigger hooks
|
92
92
|
def self.trigger(owner, event, *args)
|
93
93
|
# proceed only if there are hooks to call
|
94
|
-
|
95
|
-
return
|
96
|
-
|
97
|
-
# hooks to call for this owner and event
|
98
|
-
hooks = @registry[owner][event]
|
94
|
+
hooks = @registry.dig(owner, event)
|
95
|
+
return if hooks.nil? || hooks.empty?
|
99
96
|
|
100
97
|
# sort and call hooks according to priority and load order
|
101
98
|
hooks.sort_by { |h| @hook_priority[h] }.each do |hook|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
class Inclusion
|
5
|
+
attr_reader :site, :name, :path
|
6
|
+
private :site
|
7
|
+
|
8
|
+
def initialize(site, base, name)
|
9
|
+
@site = site
|
10
|
+
@name = name
|
11
|
+
@path = PathManager.join(base, name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def render(context)
|
15
|
+
@template ||= site.liquid_renderer.file(path).parse(content)
|
16
|
+
@template.render!(context)
|
17
|
+
rescue Liquid::Error => e
|
18
|
+
e.template_name = path
|
19
|
+
e.markup_context = "included " if e.markup_context.nil?
|
20
|
+
raise e
|
21
|
+
end
|
22
|
+
|
23
|
+
def content
|
24
|
+
@content ||= File.read(path, **site.file_read_opts)
|
25
|
+
end
|
26
|
+
|
27
|
+
def inspect
|
28
|
+
"#{self.class} #{path.inspect}"
|
29
|
+
end
|
30
|
+
alias_method :to_s, :inspect
|
31
|
+
end
|
32
|
+
end
|
@@ -5,11 +5,6 @@ require_relative "liquid_renderer/table"
|
|
5
5
|
|
6
6
|
module Jekyll
|
7
7
|
class LiquidRenderer
|
8
|
-
extend Forwardable
|
9
|
-
|
10
|
-
private def_delegator :@site, :in_source_dir, :source_dir
|
11
|
-
private def_delegator :@site, :in_theme_dir, :theme_dir
|
12
|
-
|
13
8
|
def initialize(site)
|
14
9
|
@site = site
|
15
10
|
Liquid::Template.error_mode = @site.config["liquid"]["error_mode"].to_sym
|
@@ -22,13 +17,7 @@ module Jekyll
|
|
22
17
|
end
|
23
18
|
|
24
19
|
def file(filename)
|
25
|
-
filename
|
26
|
-
filename =
|
27
|
-
if Regexp.last_match(1) == theme_dir("")
|
28
|
-
::File.join(::File.basename(Regexp.last_match(1)), Regexp.last_match(2))
|
29
|
-
else
|
30
|
-
Regexp.last_match(2)
|
31
|
-
end
|
20
|
+
filename = normalize_path(filename)
|
32
21
|
LiquidRenderer::File.new(self, filename).tap do
|
33
22
|
@stats[filename] ||= new_profile_hash
|
34
23
|
end
|
@@ -64,9 +53,23 @@ module Jekyll
|
|
64
53
|
|
65
54
|
private
|
66
55
|
|
67
|
-
def
|
68
|
-
@
|
69
|
-
|
56
|
+
def normalize_path(filename)
|
57
|
+
@normalize_path ||= {}
|
58
|
+
@normalize_path[filename] ||= begin
|
59
|
+
theme_dir = @site.theme&.root
|
60
|
+
case filename
|
61
|
+
when %r!\A(#{Regexp.escape(@site.source)}/)(?<rest>.*)!io
|
62
|
+
Regexp.last_match(:rest)
|
63
|
+
when %r!(/gems/.*)*/gems/(?<dirname>[^/]+)(?<rest>.*)!,
|
64
|
+
%r!(?<dirname>[^/]+/lib)(?<rest>.*)!
|
65
|
+
"#{Regexp.last_match(:dirname)}#{Regexp.last_match(:rest)}"
|
66
|
+
when theme_dir && %r!\A#{Regexp.escape(theme_dir)}/(?<rest>.*)!io
|
67
|
+
PathManager.join(@site.theme.basename, Regexp.last_match(:rest))
|
68
|
+
when %r!\A/(.*)!
|
69
|
+
Regexp.last_match(1)
|
70
|
+
else
|
71
|
+
filename
|
72
|
+
end
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
@@ -10,31 +10,11 @@ module Jekyll
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def to_s(num_of_rows = 50)
|
13
|
-
tabulate(data_for_table(num_of_rows))
|
13
|
+
Jekyll::Profiler.tabulate(data_for_table(num_of_rows))
|
14
14
|
end
|
15
15
|
|
16
16
|
private
|
17
17
|
|
18
|
-
def tabulate(data)
|
19
|
-
require "terminal-table"
|
20
|
-
|
21
|
-
header = data.shift
|
22
|
-
footer = data.pop
|
23
|
-
output = +"\n"
|
24
|
-
|
25
|
-
table = Terminal::Table.new do |t|
|
26
|
-
t << header
|
27
|
-
t << :separator
|
28
|
-
data.each { |row| t << row }
|
29
|
-
t << :separator
|
30
|
-
t << footer
|
31
|
-
t.style = { :alignment => :right, :border_top => false, :border_bottom => false }
|
32
|
-
t.align_column(0, :left)
|
33
|
-
end
|
34
|
-
|
35
|
-
output << table.to_s << "\n"
|
36
|
-
end
|
37
|
-
|
38
18
|
# rubocop:disable Metrics/AbcSize
|
39
19
|
def data_for_table(num_of_rows)
|
40
20
|
sorted = @stats.sort_by { |_, file_stats| -file_stats[:time] }
|
data/lib/jekyll/page.rb
CHANGED
@@ -15,6 +15,7 @@ module Jekyll
|
|
15
15
|
ATTRIBUTES_FOR_LIQUID = %w(
|
16
16
|
content
|
17
17
|
dir
|
18
|
+
excerpt
|
18
19
|
name
|
19
20
|
path
|
20
21
|
url
|
@@ -70,6 +71,38 @@ module Jekyll
|
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
74
|
+
# For backwards-compatibility in subclasses that do not redefine
|
75
|
+
# the `:to_liquid` method, stash existing definition under a new name
|
76
|
+
#
|
77
|
+
# TODO: Remove in Jekyll 5.0
|
78
|
+
alias_method :legacy_to_liquid, :to_liquid
|
79
|
+
private :legacy_to_liquid
|
80
|
+
|
81
|
+
# Private
|
82
|
+
# Subclasses can choose to optimize their `:to_liquid` method by wrapping
|
83
|
+
# it around this definition.
|
84
|
+
#
|
85
|
+
# TODO: Remove in Jekyll 5.0
|
86
|
+
def liquid_drop
|
87
|
+
@liquid_drop ||= begin
|
88
|
+
defaults = site.frontmatter_defaults.all(relative_path, type)
|
89
|
+
unless defaults.empty?
|
90
|
+
Utils.deep_merge_hashes!(data, Utils.deep_merge_hashes!(defaults, data))
|
91
|
+
end
|
92
|
+
Drops::PageDrop.new(self)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
private :liquid_drop
|
96
|
+
|
97
|
+
# Public
|
98
|
+
#
|
99
|
+
# Liquid representation of current page
|
100
|
+
#
|
101
|
+
# TODO: Remove optional parameter in Jekyll 5.0
|
102
|
+
def to_liquid(attrs = nil)
|
103
|
+
self.class == Jekyll::Page ? liquid_drop : legacy_to_liquid(attrs)
|
104
|
+
end
|
105
|
+
|
73
106
|
# The full path and filename of the post. Defined in the YAML of the post
|
74
107
|
# body.
|
75
108
|
#
|
@@ -182,5 +215,15 @@ module Jekyll
|
|
182
215
|
def write?
|
183
216
|
true
|
184
217
|
end
|
218
|
+
|
219
|
+
def excerpt_separator
|
220
|
+
@excerpt_separator ||= (data["excerpt_separator"] || site.config["excerpt_separator"]).to_s
|
221
|
+
end
|
222
|
+
|
223
|
+
def excerpt
|
224
|
+
return data["excerpt"] unless self.class == Jekyll::Page
|
225
|
+
|
226
|
+
data["excerpt"] ||= Jekyll::PageExcerpt.new(self).to_liquid unless excerpt_separator.empty?
|
227
|
+
end
|
185
228
|
end
|
186
229
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
class PageExcerpt < Excerpt
|
5
|
+
attr_reader :output, :doc
|
6
|
+
alias_method :id, :relative_path
|
7
|
+
|
8
|
+
# The Liquid representation of this instance is simply the rendered output string.
|
9
|
+
alias_method :to_liquid, :output
|
10
|
+
|
11
|
+
def initialize(doc)
|
12
|
+
super
|
13
|
+
self.output = Renderer.new(site, self, site.site_payload).run
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_with_liquid?
|
17
|
+
return false if data["render_with_liquid"] == false
|
18
|
+
|
19
|
+
Jekyll::Utils.has_liquid_construct?(content)
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
"#<#{self.class} id=#{id.inspect}>"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
class Profiler
|
5
|
+
TERMINAL_TABLE_STYLES = {
|
6
|
+
:alignment => :right,
|
7
|
+
:border_top => false,
|
8
|
+
:border_bottom => false,
|
9
|
+
}.freeze
|
10
|
+
private_constant :TERMINAL_TABLE_STYLES
|
11
|
+
|
12
|
+
def self.tabulate(table_rows)
|
13
|
+
require "terminal-table"
|
14
|
+
|
15
|
+
rows = table_rows.dup
|
16
|
+
header = rows.shift
|
17
|
+
footer = rows.pop
|
18
|
+
output = +"\n"
|
19
|
+
|
20
|
+
table = Terminal::Table.new do |t|
|
21
|
+
t << header
|
22
|
+
t << :separator
|
23
|
+
rows.each { |row| t << row }
|
24
|
+
t << :separator
|
25
|
+
t << footer
|
26
|
+
t.style = TERMINAL_TABLE_STYLES
|
27
|
+
t.align_column(0, :left)
|
28
|
+
end
|
29
|
+
|
30
|
+
output << table.to_s << "\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(site)
|
34
|
+
@site = site
|
35
|
+
end
|
36
|
+
|
37
|
+
def profile_process
|
38
|
+
profile_data = { "PHASE" => "TIME" }
|
39
|
+
total_time = 0
|
40
|
+
|
41
|
+
[:reset, :read, :generate, :render, :cleanup, :write].each do |method|
|
42
|
+
start_time = Time.now
|
43
|
+
@site.send(method)
|
44
|
+
end_time = (Time.now - start_time).round(4)
|
45
|
+
profile_data[method.to_s.upcase] = format("%.4f", end_time)
|
46
|
+
total_time += end_time
|
47
|
+
end
|
48
|
+
|
49
|
+
profile_data["TOTAL TIME"] = format("%.4f", total_time)
|
50
|
+
|
51
|
+
Jekyll.logger.info "\nBuild Process Summary:"
|
52
|
+
Jekyll.logger.info Profiler.tabulate(Array(profile_data))
|
53
|
+
|
54
|
+
Jekyll.logger.info "\nSite Render Stats:"
|
55
|
+
@site.print_stats
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/jekyll/renderer.rb
CHANGED
@@ -66,7 +66,7 @@ module Jekyll
|
|
66
66
|
# Render the document.
|
67
67
|
#
|
68
68
|
# Returns String rendered document output
|
69
|
-
# rubocop: disable AbcSize
|
69
|
+
# rubocop: disable Metrics/AbcSize
|
70
70
|
def render_document
|
71
71
|
info = {
|
72
72
|
:registers => { :site => site, :page => payload["page"] },
|
@@ -91,7 +91,7 @@ module Jekyll
|
|
91
91
|
|
92
92
|
output
|
93
93
|
end
|
94
|
-
# rubocop: enable AbcSize
|
94
|
+
# rubocop: enable Metrics/AbcSize
|
95
95
|
|
96
96
|
# Convert the document using the converters which match this renderer's document.
|
97
97
|
#
|
@@ -125,13 +125,13 @@ module Jekyll
|
|
125
125
|
LiquidRenderer.format_error(e, path || document.relative_path)
|
126
126
|
end
|
127
127
|
template.render!(payload, info)
|
128
|
-
# rubocop: disable RescueException
|
128
|
+
# rubocop: disable Lint/RescueException
|
129
129
|
rescue Exception => e
|
130
130
|
Jekyll.logger.error "Liquid Exception:",
|
131
131
|
LiquidRenderer.format_error(e, path || document.relative_path)
|
132
132
|
raise e
|
133
133
|
end
|
134
|
-
# rubocop: enable RescueException
|
134
|
+
# rubocop: enable Lint/RescueException
|
135
135
|
|
136
136
|
# Checks if the layout specified in the document actually exists
|
137
137
|
#
|
@@ -174,16 +174,10 @@ module Jekyll
|
|
174
174
|
# layout - the layout to check
|
175
175
|
# Returns nothing
|
176
176
|
def validate_layout(layout)
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
"in #{document.relative_path} does not exist."
|
182
|
-
)
|
183
|
-
elsif !layout.nil?
|
184
|
-
layout_source = layout.path.start_with?(site.source) ? :site : :theme
|
185
|
-
Jekyll.logger.debug "Layout source:", layout_source
|
186
|
-
end
|
177
|
+
return unless invalid_layout?(layout)
|
178
|
+
|
179
|
+
Jekyll.logger.warn "Build Warning:", "Layout '#{document.data["layout"]}' requested " \
|
180
|
+
"in #{document.relative_path} does not exist."
|
187
181
|
end
|
188
182
|
|
189
183
|
# Render layout content into document.output
|
@@ -197,7 +191,7 @@ module Jekyll
|
|
197
191
|
layout.content,
|
198
192
|
payload,
|
199
193
|
info,
|
200
|
-
layout.
|
194
|
+
layout.path
|
201
195
|
)
|
202
196
|
end
|
203
197
|
|
data/lib/jekyll/site.rb
CHANGED
@@ -3,14 +3,14 @@
|
|
3
3
|
module Jekyll
|
4
4
|
class Site
|
5
5
|
attr_reader :source, :dest, :cache_dir, :config
|
6
|
-
attr_accessor :layouts, :pages, :static_files, :drafts,
|
6
|
+
attr_accessor :layouts, :pages, :static_files, :drafts, :inclusions,
|
7
7
|
:exclude, :include, :lsi, :highlighter, :permalink_style,
|
8
8
|
:time, :future, :unpublished, :safe, :plugins, :limit_posts,
|
9
9
|
:show_drafts, :keep_files, :baseurl, :data, :file_read_opts,
|
10
10
|
:gems, :plugin_manager, :theme
|
11
11
|
|
12
12
|
attr_accessor :converters, :generators, :reader
|
13
|
-
attr_reader :regenerator, :liquid_renderer, :includes_load_paths
|
13
|
+
attr_reader :regenerator, :liquid_renderer, :includes_load_paths, :filter_cache, :profiler
|
14
14
|
|
15
15
|
# Public: Initialize a new Site.
|
16
16
|
#
|
@@ -23,8 +23,10 @@ module Jekyll
|
|
23
23
|
self.config = config
|
24
24
|
|
25
25
|
@cache_dir = in_source_dir(config["cache_dir"])
|
26
|
+
@filter_cache = {}
|
26
27
|
|
27
28
|
@reader = Reader.new(self)
|
29
|
+
@profiler = Profiler.new(self)
|
28
30
|
@regenerator = Regenerator.new(self)
|
29
31
|
@liquid_renderer = LiquidRenderer.new(self)
|
30
32
|
|
@@ -70,19 +72,21 @@ module Jekyll
|
|
70
72
|
#
|
71
73
|
# Returns nothing.
|
72
74
|
def process
|
75
|
+
return profiler.profile_process if config["profile"]
|
76
|
+
|
73
77
|
reset
|
74
78
|
read
|
75
79
|
generate
|
76
80
|
render
|
77
81
|
cleanup
|
78
82
|
write
|
79
|
-
print_stats if config["profile"]
|
80
83
|
end
|
81
84
|
|
82
85
|
def print_stats
|
83
86
|
Jekyll.logger.info @liquid_renderer.stats_table
|
84
87
|
end
|
85
88
|
|
89
|
+
# rubocop:disable Metrics/AbcSize
|
86
90
|
# rubocop:disable Metrics/MethodLength
|
87
91
|
#
|
88
92
|
# Reset Site details.
|
@@ -95,6 +99,7 @@ module Jekyll
|
|
95
99
|
Time.now
|
96
100
|
end
|
97
101
|
self.layouts = {}
|
102
|
+
self.inclusions = {}
|
98
103
|
self.pages = []
|
99
104
|
self.static_files = []
|
100
105
|
self.data = {}
|
@@ -114,6 +119,7 @@ module Jekyll
|
|
114
119
|
Jekyll::Hooks.trigger :site, :after_reset, self
|
115
120
|
end
|
116
121
|
# rubocop:enable Metrics/MethodLength
|
122
|
+
# rubocop:enable Metrics/AbcSize
|
117
123
|
|
118
124
|
# Load necessary libraries, plugins, converters, and generators.
|
119
125
|
#
|
@@ -431,6 +437,8 @@ module Jekyll
|
|
431
437
|
private
|
432
438
|
|
433
439
|
def load_theme_configuration(config)
|
440
|
+
return config if config["ignore_theme_config"] == true
|
441
|
+
|
434
442
|
theme_config_file = in_theme_dir("_config.yml")
|
435
443
|
return config unless File.exist?(theme_config_file)
|
436
444
|
|
@@ -470,7 +478,7 @@ module Jekyll
|
|
470
478
|
# Disable Marshaling cache to disk in Safe Mode
|
471
479
|
def configure_cache
|
472
480
|
Jekyll::Cache.cache_dir = in_source_dir(config["cache_dir"], "Jekyll/Cache")
|
473
|
-
Jekyll::Cache.disable_disk_cache! if safe
|
481
|
+
Jekyll::Cache.disable_disk_cache! if safe || config["disable_disk_cache"]
|
474
482
|
end
|
475
483
|
|
476
484
|
def configure_plugins
|
@@ -520,7 +528,8 @@ module Jekyll
|
|
520
528
|
def render_regenerated(document, payload)
|
521
529
|
return unless regenerator.regenerate?(document)
|
522
530
|
|
523
|
-
document.
|
531
|
+
document.renderer.payload = payload
|
532
|
+
document.output = document.renderer.run
|
524
533
|
document.trigger_hooks(:post_render)
|
525
534
|
end
|
526
535
|
end
|