jekyll 3.9.1 → 4.0.0.pre.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +27 -50
  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 +5 -0
  11. data/lib/jekyll/cache.rb +183 -0
  12. data/lib/jekyll/cleaner.rb +2 -1
  13. data/lib/jekyll/collection.rb +78 -8
  14. data/lib/jekyll/command.rb +31 -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 -39
  20. data/lib/jekyll/commands/new_theme.rb +30 -28
  21. data/lib/jekyll/commands/serve.rb +46 -80
  22. data/lib/jekyll/commands/serve/live_reload_reactor.rb +6 -10
  23. data/lib/jekyll/commands/serve/servlet.rb +9 -11
  24. data/lib/jekyll/configuration.rb +26 -26
  25. data/lib/jekyll/converters/identity.rb +18 -0
  26. data/lib/jekyll/converters/markdown.rb +49 -40
  27. data/lib/jekyll/converters/markdown/kramdown_parser.rb +1 -10
  28. data/lib/jekyll/converters/smartypants.rb +34 -14
  29. data/lib/jekyll/convertible.rb +11 -13
  30. data/lib/jekyll/deprecator.rb +1 -3
  31. data/lib/jekyll/document.rb +44 -41
  32. data/lib/jekyll/drops/collection_drop.rb +2 -3
  33. data/lib/jekyll/drops/document_drop.rb +2 -1
  34. data/lib/jekyll/drops/drop.rb +3 -6
  35. data/lib/jekyll/drops/excerpt_drop.rb +4 -0
  36. data/lib/jekyll/drops/site_drop.rb +4 -13
  37. data/lib/jekyll/drops/unified_payload_drop.rb +1 -0
  38. data/lib/jekyll/drops/url_drop.rb +1 -0
  39. data/lib/jekyll/entry_filter.rb +2 -1
  40. data/lib/jekyll/excerpt.rb +45 -34
  41. data/lib/jekyll/external.rb +10 -5
  42. data/lib/jekyll/filters.rb +72 -31
  43. data/lib/jekyll/filters/date_filters.rb +6 -3
  44. data/lib/jekyll/filters/grouping_filters.rb +1 -2
  45. data/lib/jekyll/filters/url_filters.rb +6 -1
  46. data/lib/jekyll/frontmatter_defaults.rb +35 -19
  47. data/lib/jekyll/hooks.rb +2 -3
  48. data/lib/jekyll/liquid_extensions.rb +0 -2
  49. data/lib/jekyll/liquid_renderer.rb +13 -1
  50. data/lib/jekyll/liquid_renderer/file.rb +14 -3
  51. data/lib/jekyll/liquid_renderer/table.rb +67 -65
  52. data/lib/jekyll/log_adapter.rb +5 -1
  53. data/lib/jekyll/page.rb +10 -11
  54. data/lib/jekyll/page_without_a_file.rb +0 -4
  55. data/lib/jekyll/plugin.rb +5 -11
  56. data/lib/jekyll/plugin_manager.rb +2 -0
  57. data/lib/jekyll/reader.rb +38 -8
  58. data/lib/jekyll/readers/data_reader.rb +7 -9
  59. data/lib/jekyll/readers/layout_reader.rb +2 -12
  60. data/lib/jekyll/readers/post_reader.rb +29 -17
  61. data/lib/jekyll/readers/static_file_reader.rb +1 -1
  62. data/lib/jekyll/readers/theme_assets_reader.rb +7 -5
  63. data/lib/jekyll/regenerator.rb +4 -12
  64. data/lib/jekyll/renderer.rb +14 -25
  65. data/lib/jekyll/site.rb +78 -34
  66. data/lib/jekyll/static_file.rb +47 -11
  67. data/lib/jekyll/stevenson.rb +2 -3
  68. data/lib/jekyll/tags/highlight.rb +22 -52
  69. data/lib/jekyll/tags/include.rb +22 -38
  70. data/lib/jekyll/tags/link.rb +11 -7
  71. data/lib/jekyll/tags/post_url.rb +17 -16
  72. data/lib/jekyll/theme.rb +12 -23
  73. data/lib/jekyll/theme_builder.rb +91 -89
  74. data/lib/jekyll/url.rb +3 -2
  75. data/lib/jekyll/utils.rb +5 -4
  76. data/lib/jekyll/utils/ansi.rb +1 -1
  77. data/lib/jekyll/utils/exec.rb +0 -1
  78. data/lib/jekyll/utils/internet.rb +2 -4
  79. data/lib/jekyll/utils/platforms.rb +8 -8
  80. data/lib/jekyll/utils/thread_event.rb +1 -5
  81. data/lib/jekyll/utils/win_tz.rb +1 -1
  82. data/lib/jekyll/version.rb +1 -1
  83. data/lib/site_template/.gitignore +2 -0
  84. data/lib/site_template/404.html +1 -0
  85. data/lib/site_template/_config.yml +17 -5
  86. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +5 -1
  87. data/lib/site_template/{about.md → about.markdown} +0 -0
  88. data/lib/site_template/{index.md → index.markdown} +0 -0
  89. data/lib/theme_template/gitignore.erb +1 -0
  90. data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -0
  91. metadata +85 -51
  92. data/lib/jekyll/converters/markdown/rdiscount_parser.rb +0 -37
  93. data/lib/jekyll/converters/markdown/redcarpet_parser.rb +0 -112
  94. 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 path and type
101
+ # Returns true if the scope applies to the given type and path
96
102
  def applies?(scope, path, type)
97
- applies_path?(scope, path) && applies_type?(scope, type)
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
- Dir.glob(abs_scope_path).each do |scope_path|
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
- # rubocop:enable Metrics/AbcSize
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
- valid_sets.select do |set|
192
- !set.key?("scope") || applies?(set["scope"], path, type)
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
@@ -2,7 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module LiquidExtensions
5
-
6
5
  # Lookup a Liquid variable in the given context.
7
6
  #
8
7
  # context - the Liquid context in question.
@@ -19,6 +18,5 @@ module Jekyll
19
18
 
20
19
  lookup || variable
21
20
  end
22
-
23
21
  end
24
22
  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
- @template = Liquid::Template.parse(content, :line_numbers => true)
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
- @template.render(*args)
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
- @template.render!(*args)
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::Table
5
- def initialize(stats)
6
- @stats = stats
7
- end
4
+ class LiquidRenderer
5
+ class Table
6
+ def initialize(stats)
7
+ @stats = stats
8
+ end
8
9
 
9
- def to_s(num_of_rows = 50)
10
- data = data_for_table(num_of_rows)
11
- widths = table_widths(data)
12
- generate_table(data, widths)
13
- end
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
- private
16
+ private
16
17
 
17
- def generate_table(data, widths)
18
- str = String.new("\n")
18
+ def generate_table(data, widths)
19
+ str = +"\n"
19
20
 
20
- table_head = data.shift
21
- str << generate_row(table_head, widths)
22
- str << generate_table_head_border(table_head, widths)
21
+ table_head = data.shift
22
+ str << generate_row(table_head, widths)
23
+ str << generate_table_head_border(table_head, widths)
23
24
 
24
- data.each do |row_data|
25
- str << generate_row(row_data, widths)
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
- str << "\n"
29
- str
30
- end
33
+ def generate_table_head_border(row_data, widths)
34
+ str = +""
31
35
 
32
- def generate_table_head_border(row_data, widths)
33
- str = String.new("")
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
- row_data.each_index do |cell_index|
36
- str << "-" * widths[cell_index]
37
- str << "-+-" unless cell_index == row_data.length - 1
41
+ str << "\n"
42
+ str
38
43
  end
39
44
 
40
- str << "\n"
41
- str
42
- end
45
+ def generate_row(row_data, widths)
46
+ str = +""
43
47
 
44
- def generate_row(row_data, widths)
45
- str = String.new("")
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
- row_data.each_with_index do |cell_data, cell_index|
48
- str << if cell_index.zero?
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 << " | " unless cell_index == row_data.length - 1
58
+ str << "\n"
59
+ str
55
60
  end
56
61
 
57
- str << "\n"
58
- str
59
- end
60
-
61
- def table_widths(data)
62
- widths = []
62
+ def table_widths(data)
63
+ widths = []
63
64
 
64
- data.each do |row|
65
- row.each_with_index do |cell, index|
66
- widths[index] = [cell.length, widths[index]].compact.max
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
- widths
71
- end
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
- def data_for_table(num_of_rows)
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
- table = [%w(Filename Count Bytes Time)]
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
- sorted.each do |filename, file_stats|
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
- table
89
- end
90
-
91
- def format_bytes(bytes)
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