jekyll 3.9.1 → 4.0.0.pre.alpha1
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 +27 -50
- data/LICENSE +1 -1
- data/README.markdown +46 -17
- data/lib/blank_template/_config.yml +3 -0
- data/lib/blank_template/_layouts/default.html +12 -0
- data/lib/blank_template/_sass/main.scss +9 -0
- data/lib/blank_template/assets/css/main.scss +4 -0
- data/lib/blank_template/index.md +8 -0
- data/lib/jekyll.rb +5 -0
- data/lib/jekyll/cache.rb +183 -0
- data/lib/jekyll/cleaner.rb +2 -1
- data/lib/jekyll/collection.rb +78 -8
- data/lib/jekyll/command.rb +31 -6
- data/lib/jekyll/commands/build.rb +11 -20
- data/lib/jekyll/commands/clean.rb +2 -0
- data/lib/jekyll/commands/doctor.rb +15 -8
- data/lib/jekyll/commands/help.rb +1 -1
- data/lib/jekyll/commands/new.rb +37 -39
- data/lib/jekyll/commands/new_theme.rb +30 -28
- data/lib/jekyll/commands/serve.rb +46 -80
- data/lib/jekyll/commands/serve/live_reload_reactor.rb +6 -10
- data/lib/jekyll/commands/serve/servlet.rb +9 -11
- data/lib/jekyll/configuration.rb +26 -26
- data/lib/jekyll/converters/identity.rb +18 -0
- data/lib/jekyll/converters/markdown.rb +49 -40
- data/lib/jekyll/converters/markdown/kramdown_parser.rb +1 -10
- data/lib/jekyll/converters/smartypants.rb +34 -14
- data/lib/jekyll/convertible.rb +11 -13
- data/lib/jekyll/deprecator.rb +1 -3
- data/lib/jekyll/document.rb +44 -41
- data/lib/jekyll/drops/collection_drop.rb +2 -3
- data/lib/jekyll/drops/document_drop.rb +2 -1
- data/lib/jekyll/drops/drop.rb +3 -6
- data/lib/jekyll/drops/excerpt_drop.rb +4 -0
- data/lib/jekyll/drops/site_drop.rb +4 -13
- data/lib/jekyll/drops/unified_payload_drop.rb +1 -0
- data/lib/jekyll/drops/url_drop.rb +1 -0
- data/lib/jekyll/entry_filter.rb +2 -1
- data/lib/jekyll/excerpt.rb +45 -34
- data/lib/jekyll/external.rb +10 -5
- data/lib/jekyll/filters.rb +72 -31
- data/lib/jekyll/filters/date_filters.rb +6 -3
- data/lib/jekyll/filters/grouping_filters.rb +1 -2
- data/lib/jekyll/filters/url_filters.rb +6 -1
- data/lib/jekyll/frontmatter_defaults.rb +35 -19
- data/lib/jekyll/hooks.rb +2 -3
- data/lib/jekyll/liquid_extensions.rb +0 -2
- data/lib/jekyll/liquid_renderer.rb +13 -1
- data/lib/jekyll/liquid_renderer/file.rb +14 -3
- data/lib/jekyll/liquid_renderer/table.rb +67 -65
- data/lib/jekyll/log_adapter.rb +5 -1
- data/lib/jekyll/page.rb +10 -11
- data/lib/jekyll/page_without_a_file.rb +0 -4
- data/lib/jekyll/plugin.rb +5 -11
- data/lib/jekyll/plugin_manager.rb +2 -0
- data/lib/jekyll/reader.rb +38 -8
- data/lib/jekyll/readers/data_reader.rb +7 -9
- data/lib/jekyll/readers/layout_reader.rb +2 -12
- data/lib/jekyll/readers/post_reader.rb +29 -17
- data/lib/jekyll/readers/static_file_reader.rb +1 -1
- data/lib/jekyll/readers/theme_assets_reader.rb +7 -5
- data/lib/jekyll/regenerator.rb +4 -12
- data/lib/jekyll/renderer.rb +14 -25
- data/lib/jekyll/site.rb +78 -34
- data/lib/jekyll/static_file.rb +47 -11
- data/lib/jekyll/stevenson.rb +2 -3
- data/lib/jekyll/tags/highlight.rb +22 -52
- data/lib/jekyll/tags/include.rb +22 -38
- data/lib/jekyll/tags/link.rb +11 -7
- data/lib/jekyll/tags/post_url.rb +17 -16
- data/lib/jekyll/theme.rb +12 -23
- data/lib/jekyll/theme_builder.rb +91 -89
- data/lib/jekyll/url.rb +3 -2
- data/lib/jekyll/utils.rb +5 -4
- data/lib/jekyll/utils/ansi.rb +1 -1
- data/lib/jekyll/utils/exec.rb +0 -1
- data/lib/jekyll/utils/internet.rb +2 -4
- data/lib/jekyll/utils/platforms.rb +8 -8
- data/lib/jekyll/utils/thread_event.rb +1 -5
- data/lib/jekyll/utils/win_tz.rb +1 -1
- data/lib/jekyll/version.rb +1 -1
- data/lib/site_template/.gitignore +2 -0
- data/lib/site_template/404.html +1 -0
- data/lib/site_template/_config.yml +17 -5
- data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +5 -1
- data/lib/site_template/{about.md → about.markdown} +0 -0
- data/lib/site_template/{index.md → index.markdown} +0 -0
- data/lib/theme_template/gitignore.erb +1 -0
- data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -0
- metadata +85 -51
- data/lib/jekyll/converters/markdown/rdiscount_parser.rb +0 -37
- data/lib/jekyll/converters/markdown/redcarpet_parser.rb +0 -112
- data/lib/jekyll/utils/rouge.rb +0 -22
@@ -41,16 +41,15 @@ module Jekyll
|
|
41
41
|
end
|
42
42
|
|
43
43
|
private
|
44
|
+
|
44
45
|
def parse_expression(str)
|
45
46
|
Liquid::Variable.new(str, Liquid::ParseContext.new)
|
46
47
|
end
|
47
48
|
|
48
|
-
private
|
49
49
|
def groupable?(element)
|
50
50
|
element.respond_to?(:group_by)
|
51
51
|
end
|
52
52
|
|
53
|
-
private
|
54
53
|
def grouped_array(groups)
|
55
54
|
groups.each_with_object([]) do |item, array|
|
56
55
|
array << {
|
@@ -10,10 +10,13 @@ module Jekyll
|
|
10
10
|
# Returns the absolute URL as a String.
|
11
11
|
def absolute_url(input)
|
12
12
|
return if input.nil?
|
13
|
+
|
13
14
|
input = input.url if input.respond_to?(:url)
|
14
15
|
return input if Addressable::URI.parse(input.to_s).absolute?
|
16
|
+
|
15
17
|
site = @context.registers[:site]
|
16
18
|
return relative_url(input) if site.config["url"].nil?
|
19
|
+
|
17
20
|
Addressable::URI.parse(
|
18
21
|
site.config["url"].to_s + relative_url(input)
|
19
22
|
).normalize.to_s
|
@@ -27,6 +30,7 @@ module Jekyll
|
|
27
30
|
# Returns a URL relative to the domain root as a String.
|
28
31
|
def relative_url(input)
|
29
32
|
return if input.nil?
|
33
|
+
|
30
34
|
input = input.url if input.respond_to?(:url)
|
31
35
|
return input if Addressable::URI.parse(input.to_s).absolute?
|
32
36
|
|
@@ -43,6 +47,7 @@ module Jekyll
|
|
43
47
|
# Returns a URL with the trailing `/index.html` removed
|
44
48
|
def strip_index(input)
|
45
49
|
return if input.nil? || input.to_s.empty?
|
50
|
+
|
46
51
|
input.sub(%r!/index\.html?$!, "/")
|
47
52
|
end
|
48
53
|
|
@@ -55,9 +60,9 @@ module Jekyll
|
|
55
60
|
|
56
61
|
def ensure_leading_slash(input)
|
57
62
|
return input if input.nil? || input.empty? || input.start_with?("/")
|
63
|
+
|
58
64
|
"/#{input}"
|
59
65
|
end
|
60
|
-
|
61
66
|
end
|
62
67
|
end
|
63
68
|
end
|
@@ -10,6 +10,11 @@ module Jekyll
|
|
10
10
|
# Initializes a new instance.
|
11
11
|
def initialize(site)
|
12
12
|
@site = site
|
13
|
+
reset
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset
|
17
|
+
@glob_cache = {}
|
13
18
|
end
|
14
19
|
|
15
20
|
def update_deprecated_types(set)
|
@@ -36,6 +41,7 @@ module Jekyll
|
|
36
41
|
def ensure_time!(set)
|
37
42
|
return set unless set.key?("values") && set["values"].key?("date")
|
38
43
|
return set if set["values"]["date"].is_a?(Time)
|
44
|
+
|
39
45
|
set["values"]["date"] = Utils.parse_date(
|
40
46
|
set["values"]["date"],
|
41
47
|
"An invalid date format was found in a front-matter default set: #{set}"
|
@@ -92,39 +98,44 @@ module Jekyll
|
|
92
98
|
# path - the path to check for
|
93
99
|
# type - the type (:post, :page or :draft) to check for
|
94
100
|
#
|
95
|
-
# Returns true if the scope applies to the given
|
101
|
+
# Returns true if the scope applies to the given type and path
|
96
102
|
def applies?(scope, path, type)
|
97
|
-
|
103
|
+
applies_type?(scope, type) && applies_path?(scope, path)
|
98
104
|
end
|
99
105
|
|
100
|
-
# rubocop:disable Metrics/AbcSize
|
101
106
|
def applies_path?(scope, path)
|
102
107
|
return true if !scope.key?("path") || scope["path"].empty?
|
103
108
|
|
104
109
|
sanitized_path = Pathname.new(sanitize_path(path))
|
105
|
-
site_path = Pathname.new(@site.source)
|
106
110
|
rel_scope_path = Pathname.new(scope["path"])
|
107
|
-
abs_scope_path = File.join(@site.source, rel_scope_path)
|
108
111
|
|
109
112
|
if scope["path"].to_s.include?("*")
|
110
|
-
|
111
|
-
scope_path = Pathname.new(scope_path).relative_path_from(site_path)
|
112
|
-
scope_path = strip_collections_dir(scope_path)
|
113
|
-
Jekyll.logger.debug "Globbed Scope Path:", scope_path
|
114
|
-
return true if path_is_subpath?(sanitized_path, scope_path)
|
115
|
-
end
|
116
|
-
false
|
113
|
+
glob_scope(sanitized_path, rel_scope_path)
|
117
114
|
else
|
118
115
|
path_is_subpath?(sanitized_path, strip_collections_dir(rel_scope_path))
|
119
116
|
end
|
120
117
|
end
|
121
|
-
|
118
|
+
|
119
|
+
def glob_scope(sanitized_path, rel_scope_path)
|
120
|
+
site_source = Pathname.new(@site.source)
|
121
|
+
abs_scope_path = site_source.join(rel_scope_path).to_s
|
122
|
+
|
123
|
+
glob_cache(abs_scope_path).each do |scope_path|
|
124
|
+
scope_path = Pathname.new(scope_path).relative_path_from(site_source)
|
125
|
+
scope_path = strip_collections_dir(scope_path)
|
126
|
+
Jekyll.logger.debug "Globbed Scope Path:", scope_path
|
127
|
+
return true if path_is_subpath?(sanitized_path, scope_path)
|
128
|
+
end
|
129
|
+
false
|
130
|
+
end
|
131
|
+
|
132
|
+
def glob_cache(path)
|
133
|
+
@glob_cache[path] ||= Dir.glob(path)
|
134
|
+
end
|
122
135
|
|
123
136
|
def path_is_subpath?(path, parent_path)
|
124
137
|
path.ascend do |ascended_path|
|
125
|
-
if ascended_path.to_s == parent_path.to_s
|
126
|
-
return true
|
127
|
-
end
|
138
|
+
return true if ascended_path.to_s == parent_path.to_s
|
128
139
|
end
|
129
140
|
|
130
141
|
false
|
@@ -134,6 +145,7 @@ module Jekyll
|
|
134
145
|
collections_dir = @site.config["collections_dir"]
|
135
146
|
slashed_coll_dir = "#{collections_dir}/"
|
136
147
|
return path if collections_dir.empty? || !path.to_s.start_with?(slashed_coll_dir)
|
148
|
+
|
137
149
|
path.sub(slashed_coll_dir, "")
|
138
150
|
end
|
139
151
|
|
@@ -188,8 +200,12 @@ module Jekyll
|
|
188
200
|
#
|
189
201
|
# Returns an array of hashes
|
190
202
|
def matching_sets(path, type)
|
191
|
-
|
192
|
-
|
203
|
+
@matched_set_cache ||= {}
|
204
|
+
@matched_set_cache[path] ||= {}
|
205
|
+
@matched_set_cache[path][type] ||= begin
|
206
|
+
valid_sets.select do |set|
|
207
|
+
!set.key?("scope") || applies?(set["scope"], path, type)
|
208
|
+
end
|
193
209
|
end
|
194
210
|
end
|
195
211
|
|
@@ -216,7 +232,7 @@ module Jekyll
|
|
216
232
|
|
217
233
|
# Sanitizes the given path by removing a leading and adding a trailing slash
|
218
234
|
|
219
|
-
SANITIZATION_REGEX = %r!\A/|(?<=[^/])\z
|
235
|
+
SANITIZATION_REGEX = %r!\A/|(?<=[^/])\z!.freeze
|
220
236
|
|
221
237
|
def sanitize_path(path)
|
222
238
|
if path.nil? || path.empty?
|
data/lib/jekyll/hooks.rb
CHANGED
@@ -60,6 +60,7 @@ module Jekyll
|
|
60
60
|
# Ensure the priority is a Fixnum
|
61
61
|
def self.priority_value(priority)
|
62
62
|
return priority if priority.is_a?(Integer)
|
63
|
+
|
63
64
|
PRIORITY_MAP[priority] || DEFAULT_PRIORITY
|
64
65
|
end
|
65
66
|
|
@@ -77,9 +78,7 @@ module Jekyll
|
|
77
78
|
"following hooks #{@registry[owner].keys.inspect}"
|
78
79
|
end
|
79
80
|
|
80
|
-
unless block.respond_to? :call
|
81
|
-
raise Uncallable, "Hooks must respond to :call"
|
82
|
-
end
|
81
|
+
raise Uncallable, "Hooks must respond to :call" unless block.respond_to? :call
|
83
82
|
|
84
83
|
insert_hook owner, event, priority, &block
|
85
84
|
end
|
@@ -18,6 +18,7 @@ module Jekyll
|
|
18
18
|
|
19
19
|
def reset
|
20
20
|
@stats = {}
|
21
|
+
@cache = {}
|
21
22
|
end
|
22
23
|
|
23
24
|
def file(filename)
|
@@ -30,7 +31,6 @@ module Jekyll
|
|
30
31
|
end
|
31
32
|
LiquidRenderer::File.new(self, filename).tap do
|
32
33
|
@stats[filename] ||= new_profile_hash
|
33
|
-
@stats[filename][:count] += 1
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -42,6 +42,10 @@ module Jekyll
|
|
42
42
|
@stats[filename][:time] += time
|
43
43
|
end
|
44
44
|
|
45
|
+
def increment_count(filename)
|
46
|
+
@stats[filename][:count] += 1
|
47
|
+
end
|
48
|
+
|
45
49
|
def stats_table(num_of_rows = 50)
|
46
50
|
LiquidRenderer::Table.new(@stats).to_s(num_of_rows)
|
47
51
|
end
|
@@ -50,6 +54,14 @@ module Jekyll
|
|
50
54
|
"#{error.message} in #{path}"
|
51
55
|
end
|
52
56
|
|
57
|
+
# A persistent cache to store and retrieve parsed templates based on the filename
|
58
|
+
# via `LiquidRenderer::File#parse`
|
59
|
+
#
|
60
|
+
# It is emptied when `self.reset` is called.
|
61
|
+
def cache
|
62
|
+
@cache ||= {}
|
63
|
+
end
|
64
|
+
|
53
65
|
private
|
54
66
|
|
55
67
|
def filename_regex
|
@@ -10,8 +10,9 @@ module Jekyll
|
|
10
10
|
|
11
11
|
def parse(content)
|
12
12
|
measure_time do
|
13
|
-
@
|
13
|
+
@renderer.cache[@filename] ||= Liquid::Template.parse(content, :line_numbers => true)
|
14
14
|
end
|
15
|
+
@template = @renderer.cache[@filename]
|
15
16
|
|
16
17
|
self
|
17
18
|
end
|
@@ -19,15 +20,20 @@ module Jekyll
|
|
19
20
|
def render(*args)
|
20
21
|
measure_time do
|
21
22
|
measure_bytes do
|
22
|
-
|
23
|
+
measure_counts do
|
24
|
+
@template.render(*args)
|
25
|
+
end
|
23
26
|
end
|
24
27
|
end
|
25
28
|
end
|
26
29
|
|
30
|
+
# This method simply 'rethrows any error' before attempting to render the template.
|
27
31
|
def render!(*args)
|
28
32
|
measure_time do
|
29
33
|
measure_bytes do
|
30
|
-
|
34
|
+
measure_counts do
|
35
|
+
@template.render!(*args)
|
36
|
+
end
|
31
37
|
end
|
32
38
|
end
|
33
39
|
end
|
@@ -38,6 +44,11 @@ module Jekyll
|
|
38
44
|
|
39
45
|
private
|
40
46
|
|
47
|
+
def measure_counts
|
48
|
+
@renderer.increment_count(@filename)
|
49
|
+
yield
|
50
|
+
end
|
51
|
+
|
41
52
|
def measure_bytes
|
42
53
|
yield.tap do |str|
|
43
54
|
@renderer.increment_bytes(@filename, str.bytesize)
|
@@ -1,96 +1,98 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Jekyll
|
4
|
-
class LiquidRenderer
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
class LiquidRenderer
|
5
|
+
class Table
|
6
|
+
def initialize(stats)
|
7
|
+
@stats = stats
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
def to_s(num_of_rows = 50)
|
11
|
+
data = data_for_table(num_of_rows)
|
12
|
+
widths = table_widths(data)
|
13
|
+
generate_table(data, widths)
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
+
private
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
def generate_table(data, widths)
|
19
|
+
str = +"\n"
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
table_head = data.shift
|
22
|
+
str << generate_row(table_head, widths)
|
23
|
+
str << generate_table_head_border(table_head, widths)
|
23
24
|
|
24
|
-
|
25
|
-
|
25
|
+
data.each do |row_data|
|
26
|
+
str << generate_row(row_data, widths)
|
27
|
+
end
|
28
|
+
|
29
|
+
str << "\n"
|
30
|
+
str
|
26
31
|
end
|
27
32
|
|
28
|
-
|
29
|
-
|
30
|
-
end
|
33
|
+
def generate_table_head_border(row_data, widths)
|
34
|
+
str = +""
|
31
35
|
|
32
|
-
|
33
|
-
|
36
|
+
row_data.each_index do |cell_index|
|
37
|
+
str << "-" * widths[cell_index]
|
38
|
+
str << "-+-" unless cell_index == row_data.length - 1
|
39
|
+
end
|
34
40
|
|
35
|
-
|
36
|
-
str
|
37
|
-
str << "-+-" unless cell_index == row_data.length - 1
|
41
|
+
str << "\n"
|
42
|
+
str
|
38
43
|
end
|
39
44
|
|
40
|
-
|
41
|
-
|
42
|
-
end
|
45
|
+
def generate_row(row_data, widths)
|
46
|
+
str = +""
|
43
47
|
|
44
|
-
|
45
|
-
|
48
|
+
row_data.each_with_index do |cell_data, cell_index|
|
49
|
+
str << if cell_index.zero?
|
50
|
+
cell_data.ljust(widths[cell_index], " ")
|
51
|
+
else
|
52
|
+
cell_data.rjust(widths[cell_index], " ")
|
53
|
+
end
|
46
54
|
|
47
|
-
|
48
|
-
|
49
|
-
cell_data.ljust(widths[cell_index], " ")
|
50
|
-
else
|
51
|
-
cell_data.rjust(widths[cell_index], " ")
|
52
|
-
end
|
55
|
+
str << " | " unless cell_index == row_data.length - 1
|
56
|
+
end
|
53
57
|
|
54
|
-
str << "
|
58
|
+
str << "\n"
|
59
|
+
str
|
55
60
|
end
|
56
61
|
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
def table_widths(data)
|
62
|
-
widths = []
|
62
|
+
def table_widths(data)
|
63
|
+
widths = []
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
65
|
+
data.each do |row|
|
66
|
+
row.each_with_index do |cell, index|
|
67
|
+
widths[index] = [cell.length, widths[index]].compact.max
|
68
|
+
end
|
67
69
|
end
|
70
|
+
|
71
|
+
widths
|
68
72
|
end
|
69
73
|
|
70
|
-
|
71
|
-
|
74
|
+
def data_for_table(num_of_rows)
|
75
|
+
sorted = @stats.sort_by { |_, file_stats| -file_stats[:time] }
|
76
|
+
sorted = sorted.slice(0, num_of_rows)
|
72
77
|
|
73
|
-
|
74
|
-
sorted = @stats.sort_by { |_, file_stats| -file_stats[:time] }
|
75
|
-
sorted = sorted.slice(0, num_of_rows)
|
78
|
+
table = [%w(Filename Count Bytes Time)]
|
76
79
|
|
77
|
-
|
80
|
+
sorted.each do |filename, file_stats|
|
81
|
+
row = []
|
82
|
+
row << filename
|
83
|
+
row << file_stats[:count].to_s
|
84
|
+
row << format_bytes(file_stats[:bytes])
|
85
|
+
row << format("%.3f", file_stats[:time])
|
86
|
+
table << row
|
87
|
+
end
|
78
88
|
|
79
|
-
|
80
|
-
row = []
|
81
|
-
row << filename
|
82
|
-
row << file_stats[:count].to_s
|
83
|
-
row << format_bytes(file_stats[:bytes])
|
84
|
-
row << format("%.3f", file_stats[:time])
|
85
|
-
table << row
|
89
|
+
table
|
86
90
|
end
|
87
91
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
bytes /= 1024.0
|
93
|
-
format("%.2fK", bytes)
|
92
|
+
def format_bytes(bytes)
|
93
|
+
bytes /= 1024.0
|
94
|
+
format("%.2fK", bytes)
|
95
|
+
end
|
94
96
|
end
|
95
97
|
end
|
96
98
|
end
|