jekyll 4.0.0.pre.alpha1 → 4.1.1
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 +58 -17
- data/lib/jekyll.rb +5 -1
- data/lib/jekyll/cache.rb +71 -64
- data/lib/jekyll/cleaner.rb +5 -5
- data/lib/jekyll/collection.rb +6 -4
- data/lib/jekyll/command.rb +4 -2
- data/lib/jekyll/commands/new.rb +4 -4
- data/lib/jekyll/commands/serve.rb +9 -1
- data/lib/jekyll/commands/serve/servlet.rb +13 -14
- data/lib/jekyll/commands/serve/websockets.rb +1 -1
- data/lib/jekyll/configuration.rb +40 -129
- data/lib/jekyll/converters/identity.rb +2 -2
- data/lib/jekyll/converters/markdown/kramdown_parser.rb +70 -9
- data/lib/jekyll/convertible.rb +21 -20
- data/lib/jekyll/document.rb +56 -31
- data/lib/jekyll/drops/document_drop.rb +12 -0
- data/lib/jekyll/drops/drop.rb +14 -8
- data/lib/jekyll/drops/site_drop.rb +11 -1
- data/lib/jekyll/drops/url_drop.rb +52 -1
- data/lib/jekyll/entry_filter.rb +38 -44
- data/lib/jekyll/excerpt.rb +3 -3
- data/lib/jekyll/filters.rb +140 -22
- data/lib/jekyll/filters/url_filters.rb +41 -14
- data/lib/jekyll/frontmatter_defaults.rb +15 -20
- 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/file.rb +10 -0
- data/lib/jekyll/liquid_renderer/table.rb +18 -61
- data/lib/jekyll/mime.types +53 -11
- data/lib/jekyll/page.rb +26 -2
- data/lib/jekyll/page_excerpt.rb +25 -0
- data/lib/jekyll/path_manager.rb +31 -0
- data/lib/jekyll/profiler.rb +58 -0
- data/lib/jekyll/reader.rb +4 -1
- 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 +5 -5
- data/lib/jekyll/readers/post_reader.rb +2 -1
- data/lib/jekyll/readers/static_file_reader.rb +3 -3
- data/lib/jekyll/readers/theme_assets_reader.rb +1 -0
- data/lib/jekyll/renderer.rb +9 -15
- data/lib/jekyll/site.rb +21 -12
- data/lib/jekyll/static_file.rb +15 -10
- data/lib/jekyll/tags/highlight.rb +2 -4
- data/lib/jekyll/tags/include.rb +67 -11
- data/lib/jekyll/tags/post_url.rb +8 -5
- data/lib/jekyll/theme.rb +19 -10
- data/lib/jekyll/url.rb +7 -3
- data/lib/jekyll/utils.rb +14 -18
- data/lib/jekyll/utils/platforms.rb +1 -1
- 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 +33 -36
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
|
@@ -47,7 +48,8 @@ module Jekyll
|
|
47
48
|
end
|
48
49
|
|
49
50
|
process(name)
|
50
|
-
read_yaml(
|
51
|
+
read_yaml(PathManager.join(base, dir), name)
|
52
|
+
generate_excerpt if site.config["page_excerpts"]
|
51
53
|
|
52
54
|
data.default_proc = proc do |_, key|
|
53
55
|
site.frontmatter_defaults.find(relative_path, type, key)
|
@@ -145,7 +147,7 @@ module Jekyll
|
|
145
147
|
|
146
148
|
# The path to the page source file, relative to the site source
|
147
149
|
def relative_path
|
148
|
-
@relative_path ||= File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).sub(%r!\A
|
150
|
+
@relative_path ||= File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).sub(%r!\A/!, "")
|
149
151
|
end
|
150
152
|
|
151
153
|
# Obtain destination path.
|
@@ -182,5 +184,27 @@ module Jekyll
|
|
182
184
|
def write?
|
183
185
|
true
|
184
186
|
end
|
187
|
+
|
188
|
+
def excerpt_separator
|
189
|
+
@excerpt_separator ||= (data["excerpt_separator"] || site.config["excerpt_separator"]).to_s
|
190
|
+
end
|
191
|
+
|
192
|
+
def excerpt
|
193
|
+
return @excerpt if defined?(@excerpt)
|
194
|
+
|
195
|
+
@excerpt = data["excerpt"]&.to_s
|
196
|
+
end
|
197
|
+
|
198
|
+
def generate_excerpt?
|
199
|
+
!excerpt_separator.empty? && self.class == Jekyll::Page && html?
|
200
|
+
end
|
201
|
+
|
202
|
+
private
|
203
|
+
|
204
|
+
def generate_excerpt
|
205
|
+
return unless generate_excerpt?
|
206
|
+
|
207
|
+
data["excerpt"] ||= Jekyll::PageExcerpt.new(self)
|
208
|
+
end
|
185
209
|
end
|
186
210
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
class PageExcerpt < Excerpt
|
5
|
+
attr_reader :doc
|
6
|
+
alias_method :id, :relative_path
|
7
|
+
|
8
|
+
EXCERPT_ATTRIBUTES = (Page::ATTRIBUTES_FOR_LIQUID - %w(excerpt)).freeze
|
9
|
+
private_constant :EXCERPT_ATTRIBUTES
|
10
|
+
|
11
|
+
def to_liquid
|
12
|
+
@to_liquid ||= doc.to_liquid(EXCERPT_ATTRIBUTES)
|
13
|
+
end
|
14
|
+
|
15
|
+
def render_with_liquid?
|
16
|
+
return false if data["render_with_liquid"] == false
|
17
|
+
|
18
|
+
Jekyll::Utils.has_liquid_construct?(content)
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
"#<#{self.class} id=#{id.inspect}>"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
# A singleton class that caches frozen instances of path strings returned from its methods.
|
5
|
+
#
|
6
|
+
# NOTE:
|
7
|
+
# This class exists because `File.join` allocates an Array and returns a new String on every
|
8
|
+
# call using **the same arguments**. Caching the result means reduced memory usage.
|
9
|
+
# However, the caches are never flushed so that they can be used even when a site is
|
10
|
+
# regenerating. The results are frozen to deter mutation of the cached string.
|
11
|
+
#
|
12
|
+
# Therefore, employ this class only for situations where caching the result is necessary
|
13
|
+
# for performance reasons.
|
14
|
+
#
|
15
|
+
class PathManager
|
16
|
+
# This class cannot be initialized from outside
|
17
|
+
private_class_method :new
|
18
|
+
|
19
|
+
# Wraps `File.join` to cache the frozen result.
|
20
|
+
# Reassigns `nil`, empty strings and empty arrays to a frozen empty string beforehand.
|
21
|
+
#
|
22
|
+
# Returns a frozen string.
|
23
|
+
def self.join(base, item)
|
24
|
+
base = "" if base.nil? || base.empty?
|
25
|
+
item = "" if item.nil? || item.empty?
|
26
|
+
@join ||= {}
|
27
|
+
@join[base] ||= {}
|
28
|
+
@join[base][item] ||= File.join(base, item).freeze
|
29
|
+
end
|
30
|
+
end
|
31
|
+
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/reader.rb
CHANGED
@@ -85,7 +85,7 @@ module Jekyll
|
|
85
85
|
def retrieve_dirs(_base, dir, dot_dirs)
|
86
86
|
dot_dirs.each do |file|
|
87
87
|
dir_path = site.in_source_dir(dir, file)
|
88
|
-
rel_path =
|
88
|
+
rel_path = PathManager.join(dir, file)
|
89
89
|
@site.reader.read_directories(rel_path) unless @site.dest.chomp("/") == dir_path
|
90
90
|
end
|
91
91
|
end
|
@@ -161,11 +161,14 @@ module Jekyll
|
|
161
161
|
end
|
162
162
|
|
163
163
|
def read_included_excludes
|
164
|
+
entry_filter = EntryFilter.new(site)
|
165
|
+
|
164
166
|
site.include.each do |entry|
|
165
167
|
next if entry == ".htaccess"
|
166
168
|
|
167
169
|
entry_path = site.in_source_dir(entry)
|
168
170
|
next if File.directory?(entry_path)
|
171
|
+
next if entry_filter.symlink?(entry_path)
|
169
172
|
|
170
173
|
read_included_file(entry_path) if File.file?(entry_path)
|
171
174
|
end
|
@@ -3,20 +3,20 @@
|
|
3
3
|
module Jekyll
|
4
4
|
class PageReader
|
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
|
-
#
|
13
|
-
# object for each file.
|
13
|
+
# Create a new `Jekyll::Page` object for each entry in a given array.
|
14
14
|
#
|
15
|
-
#
|
15
|
+
# files - An array of file names inside `@dir`
|
16
16
|
#
|
17
|
-
# Returns an array of
|
17
|
+
# Returns an array of publishable `Jekyll::Page` objects.
|
18
18
|
def read(files)
|
19
|
-
files.
|
19
|
+
files.each do |page|
|
20
20
|
@unfiltered_content << Page.new(@site, @site.source, @dir, page)
|
21
21
|
end
|
22
22
|
@unfiltered_content.select { |page| site.publisher.publish?(page) }
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module Jekyll
|
4
4
|
class PostReader
|
5
5
|
attr_reader :site, :unfiltered_content
|
6
|
+
|
6
7
|
def initialize(site)
|
7
8
|
@site = site
|
8
9
|
end
|
@@ -50,7 +51,7 @@ module Jekyll
|
|
50
51
|
# Returns klass type of content files
|
51
52
|
def read_content(dir, magic_dir, matcher)
|
52
53
|
@site.reader.get_entries(dir, magic_dir).map do |entry|
|
53
|
-
next unless entry
|
54
|
+
next unless matcher.match?(entry)
|
54
55
|
|
55
56
|
path = @site.in_source_dir(File.join(dir, magic_dir, entry))
|
56
57
|
Document.new(path,
|
@@ -3,16 +3,16 @@
|
|
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
|
-
#
|
13
|
-
# object for each file.
|
13
|
+
# Create a new StaticFile object for every entry in a given list of basenames.
|
14
14
|
#
|
15
|
-
#
|
15
|
+
# files - an array of file basenames.
|
16
16
|
#
|
17
17
|
# Returns an array of static files.
|
18
18
|
def read(files)
|
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
|
#
|
@@ -145,9 +151,9 @@ module Jekyll
|
|
145
151
|
#
|
146
152
|
# Returns a Hash containing collection name-to-instance pairs.
|
147
153
|
def collections
|
148
|
-
@collections ||=
|
149
|
-
[
|
150
|
-
end
|
154
|
+
@collections ||= collection_names.each_with_object({}) do |name, hsh|
|
155
|
+
hsh[name] = Jekyll::Collection.new(self, name)
|
156
|
+
end
|
151
157
|
end
|
152
158
|
|
153
159
|
# The list of collection names.
|
@@ -326,15 +332,15 @@ module Jekyll
|
|
326
332
|
#
|
327
333
|
# Returns an Array of Documents which should be written
|
328
334
|
def docs_to_write
|
329
|
-
|
335
|
+
documents.select(&:write?)
|
330
336
|
end
|
331
337
|
|
332
338
|
# Get all the documents
|
333
339
|
#
|
334
340
|
# Returns an Array of all Documents
|
335
341
|
def documents
|
336
|
-
|
337
|
-
|
342
|
+
collections.each_with_object(Set.new) do |(_, collection), set|
|
343
|
+
set.merge(collection.docs).merge(collection.files)
|
338
344
|
end.to_a
|
339
345
|
end
|
340
346
|
|
@@ -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
|
|
@@ -469,8 +477,8 @@ module Jekyll
|
|
469
477
|
|
470
478
|
# Disable Marshaling cache to disk in Safe Mode
|
471
479
|
def configure_cache
|
472
|
-
Jekyll::Cache.
|
473
|
-
Jekyll::Cache.disable_disk_cache! if safe
|
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"]
|
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
|