jekyll 3.8.7 → 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.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +71 -62
  3. data/LICENSE +1 -1
  4. data/README.markdown +46 -17
  5. data/lib/blank_template/_config.yml +3 -0
  6. data/lib/blank_template/_layouts/default.html +12 -0
  7. data/lib/blank_template/_sass/main.scss +9 -0
  8. data/lib/blank_template/assets/css/main.scss +4 -0
  9. data/lib/blank_template/index.md +8 -0
  10. data/lib/jekyll.rb +10 -1
  11. data/lib/jekyll/cache.rb +190 -0
  12. data/lib/jekyll/cleaner.rb +5 -4
  13. data/lib/jekyll/collection.rb +82 -10
  14. data/lib/jekyll/command.rb +33 -6
  15. data/lib/jekyll/commands/build.rb +11 -20
  16. data/lib/jekyll/commands/clean.rb +2 -0
  17. data/lib/jekyll/commands/doctor.rb +15 -8
  18. data/lib/jekyll/commands/help.rb +1 -1
  19. data/lib/jekyll/commands/new.rb +37 -35
  20. data/lib/jekyll/commands/new_theme.rb +30 -28
  21. data/lib/jekyll/commands/serve.rb +55 -81
  22. data/lib/jekyll/commands/serve/live_reload_reactor.rb +6 -10
  23. data/lib/jekyll/commands/serve/servlet.rb +22 -25
  24. data/lib/jekyll/commands/serve/websockets.rb +1 -1
  25. data/lib/jekyll/configuration.rb +61 -149
  26. data/lib/jekyll/converters/identity.rb +18 -0
  27. data/lib/jekyll/converters/markdown.rb +49 -40
  28. data/lib/jekyll/converters/markdown/kramdown_parser.rb +84 -11
  29. data/lib/jekyll/converters/smartypants.rb +34 -14
  30. data/lib/jekyll/convertible.rb +30 -31
  31. data/lib/jekyll/deprecator.rb +1 -3
  32. data/lib/jekyll/document.rb +89 -61
  33. data/lib/jekyll/drops/collection_drop.rb +2 -3
  34. data/lib/jekyll/drops/document_drop.rb +14 -1
  35. data/lib/jekyll/drops/drop.rb +17 -14
  36. data/lib/jekyll/drops/excerpt_drop.rb +4 -0
  37. data/lib/jekyll/drops/page_drop.rb +18 -0
  38. data/lib/jekyll/drops/site_drop.rb +6 -5
  39. data/lib/jekyll/drops/unified_payload_drop.rb +1 -0
  40. data/lib/jekyll/drops/url_drop.rb +53 -1
  41. data/lib/jekyll/entry_filter.rb +42 -45
  42. data/lib/jekyll/excerpt.rb +45 -34
  43. data/lib/jekyll/external.rb +10 -5
  44. data/lib/jekyll/filters.rb +200 -40
  45. data/lib/jekyll/filters/date_filters.rb +6 -3
  46. data/lib/jekyll/filters/grouping_filters.rb +1 -2
  47. data/lib/jekyll/filters/url_filters.rb +46 -14
  48. data/lib/jekyll/frontmatter_defaults.rb +46 -35
  49. data/lib/jekyll/hooks.rb +4 -8
  50. data/lib/jekyll/inclusion.rb +32 -0
  51. data/lib/jekyll/liquid_extensions.rb +0 -2
  52. data/lib/jekyll/liquid_renderer.rb +31 -16
  53. data/lib/jekyll/liquid_renderer/file.rb +24 -3
  54. data/lib/jekyll/liquid_renderer/table.rb +36 -77
  55. data/lib/jekyll/log_adapter.rb +5 -1
  56. data/lib/jekyll/mime.types +53 -11
  57. data/lib/jekyll/page.rb +54 -12
  58. data/lib/jekyll/page_excerpt.rb +26 -0
  59. data/lib/jekyll/page_without_a_file.rb +0 -4
  60. data/lib/jekyll/path_manager.rb +31 -0
  61. data/lib/jekyll/plugin.rb +5 -11
  62. data/lib/jekyll/plugin_manager.rb +2 -0
  63. data/lib/jekyll/profiler.rb +58 -0
  64. data/lib/jekyll/reader.rb +42 -9
  65. data/lib/jekyll/readers/collection_reader.rb +1 -0
  66. data/lib/jekyll/readers/data_reader.rb +8 -9
  67. data/lib/jekyll/readers/layout_reader.rb +3 -12
  68. data/lib/jekyll/readers/page_reader.rb +5 -5
  69. data/lib/jekyll/readers/post_reader.rb +31 -18
  70. data/lib/jekyll/readers/static_file_reader.rb +4 -4
  71. data/lib/jekyll/readers/theme_assets_reader.rb +8 -5
  72. data/lib/jekyll/regenerator.rb +4 -12
  73. data/lib/jekyll/renderer.rb +23 -40
  74. data/lib/jekyll/site.rb +91 -38
  75. data/lib/jekyll/static_file.rb +62 -21
  76. data/lib/jekyll/stevenson.rb +2 -3
  77. data/lib/jekyll/tags/highlight.rb +19 -51
  78. data/lib/jekyll/tags/include.rb +82 -42
  79. data/lib/jekyll/tags/link.rb +11 -7
  80. data/lib/jekyll/tags/post_url.rb +25 -21
  81. data/lib/jekyll/theme.rb +16 -18
  82. data/lib/jekyll/theme_builder.rb +91 -89
  83. data/lib/jekyll/url.rb +10 -5
  84. data/lib/jekyll/utils.rb +18 -21
  85. data/lib/jekyll/utils/ansi.rb +1 -1
  86. data/lib/jekyll/utils/exec.rb +0 -1
  87. data/lib/jekyll/utils/internet.rb +2 -4
  88. data/lib/jekyll/utils/platforms.rb +8 -8
  89. data/lib/jekyll/utils/thread_event.rb +1 -5
  90. data/lib/jekyll/utils/win_tz.rb +2 -2
  91. data/lib/jekyll/version.rb +1 -1
  92. data/lib/site_template/.gitignore +2 -0
  93. data/lib/site_template/404.html +1 -0
  94. data/lib/site_template/_config.yml +17 -5
  95. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +5 -1
  96. data/lib/site_template/{about.md → about.markdown} +0 -0
  97. data/lib/site_template/{index.md → index.markdown} +0 -0
  98. data/lib/theme_template/gitignore.erb +1 -0
  99. data/lib/theme_template/theme.gemspec.erb +1 -4
  100. data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -0
  101. metadata +69 -31
  102. data/lib/jekyll/converters/markdown/rdiscount_parser.rb +0 -37
  103. data/lib/jekyll/converters/markdown/redcarpet_parser.rb +0 -112
  104. data/lib/jekyll/utils/rouge.rb +0 -22
@@ -3,20 +3,20 @@
3
3
  module Jekyll
4
4
  class StaticFileReader
5
5
  attr_reader :site, :dir, :unfiltered_content
6
+
6
7
  def initialize(site, dir)
7
8
  @site = site
8
9
  @dir = dir
9
10
  @unfiltered_content = []
10
11
  end
11
12
 
12
- # Read all the files in <source>/<dir>/ for Yaml header and create a new Page
13
- # object for each file.
13
+ # Create a new StaticFile object for every entry in a given list of basenames.
14
14
  #
15
- # dir - The String relative path of the directory to read.
15
+ # files - an array of file basenames.
16
16
  #
17
17
  # Returns an array of static files.
18
18
  def read(files)
19
- files.map do |file|
19
+ files.each do |file|
20
20
  @unfiltered_content << StaticFile.new(@site, @site.source, @dir, file)
21
21
  end
22
22
  @unfiltered_content
@@ -3,15 +3,17 @@
3
3
  module Jekyll
4
4
  class ThemeAssetsReader
5
5
  attr_reader :site
6
+
6
7
  def initialize(site)
7
8
  @site = site
8
9
  end
9
10
 
10
11
  def read
11
- return unless site.theme && site.theme.assets_path
12
+ return unless site.theme&.assets_path
12
13
 
13
14
  Find.find(site.theme.assets_path) do |path|
14
15
  next if File.directory?(path)
16
+
15
17
  if File.symlink?(path)
16
18
  Jekyll.logger.warn "Theme reader:", "Ignored symlinked asset: #{path}"
17
19
  else
@@ -21,6 +23,7 @@ module Jekyll
21
23
  end
22
24
 
23
25
  private
26
+
24
27
  def read_theme_asset(path)
25
28
  base = site.theme.root
26
29
  dir = File.dirname(path.sub("#{site.theme.root}/", ""))
@@ -28,18 +31,18 @@ module Jekyll
28
31
 
29
32
  if Utils.has_yaml_header?(path)
30
33
  append_unless_exists site.pages,
31
- Jekyll::Page.new(site, base, dir, name)
34
+ Jekyll::Page.new(site, base, dir, name)
32
35
  else
33
36
  append_unless_exists site.static_files,
34
- Jekyll::StaticFile.new(site, base, "/#{dir}", name)
37
+ Jekyll::StaticFile.new(site, base, "/#{dir}", name)
35
38
  end
36
39
  end
37
40
 
38
41
  def append_unless_exists(haystack, new_item)
39
42
  if haystack.any? { |file| file.relative_path == new_item.relative_path }
40
43
  Jekyll.logger.debug "Theme:",
41
- "Ignoring #{new_item.relative_path} in theme due to existing file " \
42
- "with that path in site."
44
+ "Ignoring #{new_item.relative_path} in theme due to existing file " \
45
+ "with that path in site."
43
46
  return
44
47
  end
45
48
 
@@ -21,6 +21,7 @@ module Jekyll
21
21
  # Returns a boolean.
22
22
  def regenerate?(document)
23
23
  return true if disabled
24
+
24
25
  case document
25
26
  when Page
26
27
  regenerate_page?(document)
@@ -28,9 +29,7 @@ module Jekyll
28
29
  regenerate_document?(document)
29
30
  else
30
31
  source_path = document.respond_to?(:path) ? document.path : nil
31
- dest_path = if document.respond_to?(:destination)
32
- document.destination(@site.dest)
33
- end
32
+ dest_path = document.destination(@site.dest) if document.respond_to?(:destination)
34
33
  source_modified_or_dest_missing?(source_path, dest_path)
35
34
  end
36
35
  end
@@ -89,9 +88,7 @@ module Jekyll
89
88
  return true if path.nil?
90
89
 
91
90
  # Check for path in cache
92
- if cache.key? path
93
- return cache[path]
94
- end
91
+ return cache[path] if cache.key? path
95
92
 
96
93
  if metadata[path]
97
94
  # If we have seen this file before,
@@ -165,7 +162,6 @@ module Jekyll
165
162
  end
166
163
  end
167
164
 
168
- private
169
165
  def regenerate_page?(document)
170
166
  document.asset_file? || document.data["regenerate"] ||
171
167
  source_modified_or_dest_missing?(
@@ -173,7 +169,6 @@ module Jekyll
173
169
  )
174
170
  end
175
171
 
176
- private
177
172
  def regenerate_document?(document)
178
173
  !document.write? || document.data["regenerate"] ||
179
174
  source_modified_or_dest_missing?(
@@ -181,14 +176,11 @@ module Jekyll
181
176
  )
182
177
  end
183
178
 
184
- private
185
179
  def existing_file_modified?(path)
186
180
  # If one of this file dependencies have been modified,
187
181
  # set the regeneration bit for both the dependency and the file to true
188
182
  metadata[path]["deps"].each do |dependency|
189
- if modified?(dependency)
190
- return cache[dependency] = cache[path] = true
191
- end
183
+ return cache[dependency] = cache[path] = true if modified?(dependency)
192
184
  end
193
185
 
194
186
  if File.exist?(path) && metadata[path]["mtime"].eql?(File.mtime(path))
@@ -9,6 +9,7 @@ module Jekyll
9
9
  @site = site
10
10
  @document = document
11
11
  @payload = site_payload
12
+ @layouts = nil
12
13
  end
13
14
 
14
15
  # Fetches the payload used in Liquid rendering.
@@ -65,7 +66,7 @@ module Jekyll
65
66
  # Render the document.
66
67
  #
67
68
  # Returns String rendered document output
68
- # rubocop: disable AbcSize
69
+ # rubocop: disable Metrics/AbcSize
69
70
  def render_document
70
71
  info = {
71
72
  :registers => { :site => site, :page => payload["page"] },
@@ -90,7 +91,7 @@ module Jekyll
90
91
 
91
92
  output
92
93
  end
93
- # rubocop: enable AbcSize
94
+ # rubocop: enable Metrics/AbcSize
94
95
 
95
96
  # Convert the document using the converters which match this renderer's document.
96
97
  #
@@ -101,8 +102,8 @@ module Jekyll
101
102
  converter.convert output
102
103
  rescue StandardError => e
103
104
  Jekyll.logger.error "Conversion error:",
104
- "#{converter.class} encountered an error while "\
105
- "converting '#{document.relative_path}':"
105
+ "#{converter.class} encountered an error while "\
106
+ "converting '#{document.relative_path}':"
106
107
  Jekyll.logger.error("", e.to_s)
107
108
  raise e
108
109
  end
@@ -121,16 +122,16 @@ module Jekyll
121
122
  template = site.liquid_renderer.file(path).parse(content)
122
123
  template.warnings.each do |e|
123
124
  Jekyll.logger.warn "Liquid Warning:",
124
- LiquidRenderer.format_error(e, path || document.relative_path)
125
+ LiquidRenderer.format_error(e, path || document.relative_path)
125
126
  end
126
127
  template.render!(payload, info)
127
- # rubocop: disable RescueException
128
+ # rubocop: disable Lint/RescueException
128
129
  rescue Exception => e
129
130
  Jekyll.logger.error "Liquid Exception:",
130
- LiquidRenderer.format_error(e, path || document.relative_path)
131
+ LiquidRenderer.format_error(e, path || document.relative_path)
131
132
  raise e
132
133
  end
133
- # rubocop: enable RescueException
134
+ # rubocop: enable Lint/RescueException
134
135
 
135
136
  # Checks if the layout specified in the document actually exists
136
137
  #
@@ -158,36 +159,30 @@ module Jekyll
158
159
  output = render_layout(output, layout, info)
159
160
  add_regenerator_dependencies(layout)
160
161
 
161
- if (layout = site.layouts[layout.data["layout"]])
162
- break if used.include?(layout)
163
- used << layout
164
- end
162
+ next unless (layout = site.layouts[layout.data["layout"]])
163
+ break if used.include?(layout)
164
+
165
+ used << layout
165
166
  end
166
167
  output
167
168
  end
168
169
 
170
+ private
171
+
169
172
  # Checks if the layout specified in the document actually exists
170
173
  #
171
174
  # layout - the layout to check
172
175
  # Returns nothing
173
- private
174
176
  def validate_layout(layout)
175
- if invalid_layout?(layout)
176
- Jekyll.logger.warn(
177
- "Build Warning:",
178
- "Layout '#{document.data["layout"]}' requested "\
179
- "in #{document.relative_path} does not exist."
180
- )
181
- elsif !layout.nil?
182
- layout_source = layout.path.start_with?(site.source) ? :site : :theme
183
- Jekyll.logger.debug "Layout source:", layout_source
184
- 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."
185
181
  end
186
182
 
187
183
  # Render layout content into document.output
188
184
  #
189
185
  # Returns String rendered content
190
- private
191
186
  def render_layout(output, layout, info)
192
187
  payload["content"] = output
193
188
  payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
@@ -196,13 +191,13 @@ module Jekyll
196
191
  layout.content,
197
192
  payload,
198
193
  info,
199
- layout.relative_path
194
+ layout.path
200
195
  )
201
196
  end
202
197
 
203
- private
204
198
  def add_regenerator_dependencies(layout)
205
199
  return unless document.write?
200
+
206
201
  site.regenerator.add_dependency(
207
202
  site.in_source_dir(document.path),
208
203
  layout.path
@@ -212,18 +207,14 @@ module Jekyll
212
207
  # Set page content to payload and assign pager if document has one.
213
208
  #
214
209
  # Returns nothing
215
- private
216
210
  def assign_pages!
217
211
  payload["page"] = document.to_liquid
218
- payload["paginator"] = if document.respond_to?(:pager)
219
- document.pager.to_liquid
220
- end
212
+ payload["paginator"] = (document.pager.to_liquid if document.respond_to?(:pager))
221
213
  end
222
214
 
223
215
  # Set related posts to payload if document is a post.
224
216
  #
225
217
  # Returns nothing
226
- private
227
218
  def assign_current_document!
228
219
  payload["site"].current_document = document
229
220
  end
@@ -231,21 +222,16 @@ module Jekyll
231
222
  # Set highlighter prefix and suffix
232
223
  #
233
224
  # Returns nothing
234
- private
235
225
  def assign_highlighter_options!
236
226
  payload["highlighter_prefix"] = converters.first.highlighter_prefix
237
227
  payload["highlighter_suffix"] = converters.first.highlighter_suffix
238
228
  end
239
229
 
240
- private
241
230
  def assign_layout_data!
242
231
  layout = layouts[document.data["layout"]]
243
- if layout
244
- payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
245
- end
232
+ payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {}) if layout
246
233
  end
247
234
 
248
- private
249
235
  def permalink_ext
250
236
  document_permalink = document.permalink
251
237
  if document_permalink && !document_permalink.end_with?("/")
@@ -254,7 +240,6 @@ module Jekyll
254
240
  end
255
241
  end
256
242
 
257
- private
258
243
  def converter_output_ext
259
244
  if output_exts.size == 1
260
245
  output_exts.last
@@ -263,14 +248,12 @@ module Jekyll
263
248
  end
264
249
  end
265
250
 
266
- private
267
251
  def output_exts
268
252
  @output_exts ||= converters.map do |c|
269
253
  c.output_ext(document.extname)
270
254
  end.compact
271
255
  end
272
256
 
273
- private
274
257
  def liquid_options
275
258
  @liquid_options ||= site.config["liquid"]
276
259
  end
@@ -2,15 +2,15 @@
2
2
 
3
3
  module Jekyll
4
4
  class Site
5
- attr_reader :source, :dest, :config
6
- attr_accessor :layouts, :pages, :static_files, :drafts,
5
+ attr_reader :source, :dest, :cache_dir, :config
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
  #
@@ -22,7 +22,11 @@ module Jekyll
22
22
 
23
23
  self.config = config
24
24
 
25
+ @cache_dir = in_source_dir(config["cache_dir"])
26
+ @filter_cache = {}
27
+
25
28
  @reader = Reader.new(self)
29
+ @profiler = Profiler.new(self)
26
30
  @regenerator = Regenerator.new(self)
27
31
  @liquid_renderer = LiquidRenderer.new(self)
28
32
 
@@ -44,13 +48,14 @@ module Jekyll
44
48
  @config = config.clone
45
49
 
46
50
  %w(safe lsi highlighter baseurl exclude include future unpublished
47
- show_drafts limit_posts keep_files).each do |opt|
48
- self.send("#{opt}=", config[opt])
51
+ show_drafts limit_posts keep_files).each do |opt|
52
+ send("#{opt}=", config[opt])
49
53
  end
50
54
 
51
55
  # keep using `gems` to avoid breaking change
52
56
  self.gems = config["plugins"]
53
57
 
58
+ configure_cache
54
59
  configure_plugins
55
60
  configure_theme
56
61
  configure_include_paths
@@ -58,6 +63,8 @@ module Jekyll
58
63
 
59
64
  self.permalink_style = config["permalink"].to_sym
60
65
 
66
+ # Read in a _config.yml from the current theme-gem at the very end.
67
+ @config = load_theme_configuration(config) if theme
61
68
  @config
62
69
  end
63
70
 
@@ -65,19 +72,23 @@ module Jekyll
65
72
  #
66
73
  # Returns nothing.
67
74
  def process
75
+ return profiler.profile_process if config["profile"]
76
+
68
77
  reset
69
78
  read
70
79
  generate
71
80
  render
72
81
  cleanup
73
82
  write
74
- print_stats if config["profile"]
75
83
  end
76
84
 
77
85
  def print_stats
78
86
  Jekyll.logger.info @liquid_renderer.stats_table
79
87
  end
80
88
 
89
+ # rubocop:disable Metrics/AbcSize
90
+ # rubocop:disable Metrics/MethodLength
91
+ #
81
92
  # Reset Site details.
82
93
  #
83
94
  # Returns nothing
@@ -88,22 +99,27 @@ module Jekyll
88
99
  Time.now
89
100
  end
90
101
  self.layouts = {}
102
+ self.inclusions = {}
91
103
  self.pages = []
92
104
  self.static_files = []
93
105
  self.data = {}
106
+ @post_attr_hash = {}
94
107
  @site_data = nil
95
108
  @collections = nil
109
+ @documents = nil
96
110
  @docs_to_write = nil
97
111
  @regenerator.clear_cache
98
112
  @liquid_renderer.reset
99
113
  @site_cleaner = nil
114
+ frontmatter_defaults.reset
100
115
 
101
- if limit_posts < 0
102
- raise ArgumentError, "limit_posts must be a non-negative number"
103
- end
116
+ raise ArgumentError, "limit_posts must be a non-negative number" if limit_posts.negative?
104
117
 
118
+ Jekyll::Cache.clear_if_config_changed config
105
119
  Jekyll::Hooks.trigger :site, :after_reset, self
106
120
  end
121
+ # rubocop:enable Metrics/MethodLength
122
+ # rubocop:enable Metrics/AbcSize
107
123
 
108
124
  # Load necessary libraries, plugins, converters, and generators.
109
125
  #
@@ -124,7 +140,7 @@ module Jekyll
124
140
  Pathname.new(source).ascend do |path|
125
141
  if path == dest_pathname
126
142
  raise Errors::FatalException,
127
- "Destination directory cannot be or contain the Source directory."
143
+ "Destination directory cannot be or contain the Source directory."
128
144
  end
129
145
  end
130
146
  end
@@ -135,9 +151,9 @@ module Jekyll
135
151
  #
136
152
  # Returns a Hash containing collection name-to-instance pairs.
137
153
  def collections
138
- @collections ||= Hash[collection_names.map do |coll|
139
- [coll, Jekyll::Collection.new(self, coll)]
140
- end]
154
+ @collections ||= collection_names.each_with_object({}) do |name, hsh|
155
+ hsh[name] = Jekyll::Collection.new(self, name)
156
+ end
141
157
  end
142
158
 
143
159
  # The list of collection names.
@@ -174,7 +190,7 @@ module Jekyll
174
190
  start = Time.now
175
191
  generator.generate(self)
176
192
  Jekyll.logger.debug "Generating:",
177
- "#{generator.class} finished in #{Time.now - start} seconds."
193
+ "#{generator.class} finished in #{Time.now - start} seconds."
178
194
  end
179
195
  end
180
196
 
@@ -232,12 +248,14 @@ module Jekyll
232
248
  def post_attr_hash(post_attr)
233
249
  # Build a hash map based on the specified post attribute ( post attr =>
234
250
  # array of posts ) then sort each array in reverse order.
235
- hash = Hash.new { |h, key| h[key] = [] }
236
- posts.docs.each do |p|
237
- p.data[post_attr].each { |t| hash[t] << p } if p.data[post_attr]
251
+ @post_attr_hash[post_attr] ||= begin
252
+ hash = Hash.new { |h, key| h[key] = [] }
253
+ posts.docs.each do |p|
254
+ p.data[post_attr]&.each { |t| hash[t] << p }
255
+ end
256
+ hash.each_value { |posts| posts.sort!.reverse! }
257
+ hash
238
258
  end
239
- hash.each_value { |posts| posts.sort!.reverse! }
240
- hash
241
259
  end
242
260
 
243
261
  def tags
@@ -303,10 +321,10 @@ module Jekyll
303
321
  def relative_permalinks_are_deprecated
304
322
  if config["relative_permalinks"]
305
323
  Jekyll.logger.abort_with "Since v3.0, permalinks for pages" \
306
- " in subfolders must be relative to the" \
307
- " site source directory, not the parent" \
308
- " directory. Check https://jekyllrb.com/docs/upgrading/"\
309
- " for more info."
324
+ " in subfolders must be relative to the" \
325
+ " site source directory, not the parent" \
326
+ " directory. Check https://jekyllrb.com/docs/upgrading/"\
327
+ " for more info."
310
328
  end
311
329
  end
312
330
 
@@ -377,6 +395,7 @@ module Jekyll
377
395
  # Returns a path which is prefixed with the theme root directory.
378
396
  def in_theme_dir(*paths)
379
397
  return nil unless theme
398
+
380
399
  paths.reduce(theme.root) do |base, path|
381
400
  Jekyll.sanitized_path(base, path)
382
401
  end
@@ -394,6 +413,18 @@ module Jekyll
394
413
  end
395
414
  end
396
415
 
416
+ # Public: Prefix a given path with the cache directory.
417
+ #
418
+ # paths - (optional) path elements to a file or directory within the
419
+ # cache directory
420
+ #
421
+ # Returns a path which is prefixed with the cache directory.
422
+ def in_cache_dir(*paths)
423
+ paths.reduce(cache_dir) do |base, path|
424
+ Jekyll.sanitized_path(base, path)
425
+ end
426
+ end
427
+
397
428
  # Public: The full path to the directory that houses all the collections registered
398
429
  # with the current site.
399
430
  #
@@ -403,14 +434,36 @@ module Jekyll
403
434
  @collections_path ||= dir_str.empty? ? source : in_source_dir(dir_str)
404
435
  end
405
436
 
437
+ private
438
+
439
+ def load_theme_configuration(config)
440
+ return config if config["ignore_theme_config"] == true
441
+
442
+ theme_config_file = in_theme_dir("_config.yml")
443
+ return config unless File.exist?(theme_config_file)
444
+
445
+ # Bail out if the theme_config_file is a symlink file irrespective of safe mode
446
+ return config if File.symlink?(theme_config_file)
447
+
448
+ theme_config = SafeYAML.load_file(theme_config_file)
449
+ return config unless theme_config.is_a?(Hash)
450
+
451
+ Jekyll.logger.info "Theme Config file:", theme_config_file
452
+
453
+ # theme_config should not be overriding Jekyll's defaults
454
+ theme_config.delete_if { |key, _| Configuration::DEFAULTS.key?(key) }
455
+
456
+ # Override theme_config with existing config and return the result.
457
+ Utils.deep_merge_hashes(theme_config, config)
458
+ end
459
+
406
460
  # Limits the current posts; removes the posts which exceed the limit_posts
407
461
  #
408
462
  # Returns nothing
409
- private
410
463
  def limit_posts!
411
- if limit_posts > 0
464
+ if limit_posts.positive?
412
465
  limit = posts.docs.length < limit_posts ? posts.docs.length : limit_posts
413
- self.posts.docs = posts.docs[-limit, limit]
466
+ posts.docs = posts.docs[-limit, limit]
414
467
  end
415
468
  end
416
469
 
@@ -418,18 +471,21 @@ module Jekyll
418
471
  # already exist.
419
472
  #
420
473
  # Returns The Cleaner
421
- private
422
474
  def site_cleaner
423
475
  @site_cleaner ||= Cleaner.new(self)
424
476
  end
425
477
 
426
- private
478
+ # Disable Marshaling cache to disk in Safe Mode
479
+ def configure_cache
480
+ Jekyll::Cache.cache_dir = in_source_dir(config["cache_dir"], "Jekyll/Cache")
481
+ Jekyll::Cache.disable_disk_cache! if safe || config["disable_disk_cache"]
482
+ end
483
+
427
484
  def configure_plugins
428
485
  self.plugin_manager = Jekyll::PluginManager.new(self)
429
486
  self.plugins = plugin_manager.plugins_path
430
487
  end
431
488
 
432
- private
433
489
  def configure_theme
434
490
  self.theme = nil
435
491
  return if config["theme"].nil?
@@ -444,20 +500,17 @@ module Jekyll
444
500
  end
445
501
  end
446
502
 
447
- private
448
503
  def configure_include_paths
449
504
  @includes_load_paths = Array(in_source_dir(config["includes_dir"].to_s))
450
- @includes_load_paths << theme.includes_path if theme && theme.includes_path
505
+ @includes_load_paths << theme.includes_path if theme&.includes_path
451
506
  end
452
507
 
453
- private
454
508
  def configure_file_read_opts
455
509
  self.file_read_opts = {}
456
- self.file_read_opts[:encoding] = config["encoding"] if config["encoding"]
510
+ file_read_opts[:encoding] = config["encoding"] if config["encoding"]
457
511
  self.file_read_opts = Jekyll::Utils.merged_file_read_opts(self, {})
458
512
  end
459
513
 
460
- private
461
514
  def render_docs(payload)
462
515
  collections.each_value do |collection|
463
516
  collection.docs.each do |document|
@@ -466,17 +519,17 @@ module Jekyll
466
519
  end
467
520
  end
468
521
 
469
- private
470
522
  def render_pages(payload)
471
- pages.flatten.each do |page|
523
+ pages.each do |page|
472
524
  render_regenerated(page, payload)
473
525
  end
474
526
  end
475
527
 
476
- private
477
528
  def render_regenerated(document, payload)
478
529
  return unless regenerator.regenerate?(document)
479
- document.output = Jekyll::Renderer.new(self, document, payload).run
530
+
531
+ document.renderer.payload = payload
532
+ document.output = document.renderer.run
480
533
  document.trigger_hooks(:post_render)
481
534
  end
482
535
  end