jekyll 4.2.1 → 4.3.2

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +474 -350
  3. data/LICENSE +21 -21
  4. data/README.markdown +83 -86
  5. data/exe/jekyll +57 -57
  6. data/lib/blank_template/_config.yml +3 -3
  7. data/lib/blank_template/_layouts/default.html +12 -12
  8. data/lib/blank_template/_sass/{main.scss → base.scss} +9 -9
  9. data/lib/blank_template/assets/css/main.scss +4 -4
  10. data/lib/blank_template/index.md +8 -8
  11. data/lib/jekyll/cache.rb +186 -190
  12. data/lib/jekyll/cleaner.rb +111 -111
  13. data/lib/jekyll/collection.rb +310 -309
  14. data/lib/jekyll/command.rb +105 -105
  15. data/lib/jekyll/commands/build.rb +82 -93
  16. data/lib/jekyll/commands/clean.rb +44 -45
  17. data/lib/jekyll/commands/doctor.rb +177 -177
  18. data/lib/jekyll/commands/help.rb +34 -34
  19. data/lib/jekyll/commands/new.rb +168 -169
  20. data/lib/jekyll/commands/new_theme.rb +39 -40
  21. data/lib/jekyll/commands/serve/live_reload_reactor.rb +119 -122
  22. data/lib/jekyll/commands/serve/livereload_assets/livereload.js +1183 -1183
  23. data/lib/jekyll/commands/serve/mime_types_charset.json +71 -0
  24. data/lib/jekyll/commands/serve/servlet.rb +206 -202
  25. data/lib/jekyll/commands/serve/websockets.rb +81 -81
  26. data/lib/jekyll/commands/serve.rb +367 -362
  27. data/lib/jekyll/configuration.rb +313 -313
  28. data/lib/jekyll/converter.rb +54 -54
  29. data/lib/jekyll/converters/identity.rb +41 -41
  30. data/lib/jekyll/converters/markdown/kramdown_parser.rb +197 -199
  31. data/lib/jekyll/converters/markdown.rb +113 -113
  32. data/lib/jekyll/converters/smartypants.rb +70 -70
  33. data/lib/jekyll/convertible.rb +257 -257
  34. data/lib/jekyll/deprecator.rb +50 -50
  35. data/lib/jekyll/document.rb +543 -544
  36. data/lib/jekyll/drops/collection_drop.rb +20 -20
  37. data/lib/jekyll/drops/document_drop.rb +74 -70
  38. data/lib/jekyll/drops/drop.rb +293 -293
  39. data/lib/jekyll/drops/excerpt_drop.rb +23 -19
  40. data/lib/jekyll/drops/jekyll_drop.rb +32 -32
  41. data/lib/jekyll/drops/site_drop.rb +66 -66
  42. data/lib/jekyll/drops/static_file_drop.rb +14 -14
  43. data/lib/jekyll/drops/theme_drop.rb +36 -0
  44. data/lib/jekyll/drops/unified_payload_drop.rb +30 -26
  45. data/lib/jekyll/drops/url_drop.rb +140 -140
  46. data/lib/jekyll/entry_filter.rb +117 -121
  47. data/lib/jekyll/errors.rb +20 -20
  48. data/lib/jekyll/excerpt.rb +200 -201
  49. data/lib/jekyll/external.rb +75 -79
  50. data/lib/jekyll/filters/date_filters.rb +110 -110
  51. data/lib/jekyll/filters/grouping_filters.rb +64 -64
  52. data/lib/jekyll/filters/url_filters.rb +98 -98
  53. data/lib/jekyll/filters.rb +532 -535
  54. data/lib/jekyll/frontmatter_defaults.rb +238 -240
  55. data/lib/jekyll/generator.rb +5 -5
  56. data/lib/jekyll/hooks.rb +107 -107
  57. data/lib/jekyll/inclusion.rb +32 -32
  58. data/lib/jekyll/layout.rb +55 -67
  59. data/lib/jekyll/liquid_extensions.rb +22 -22
  60. data/lib/jekyll/liquid_renderer/file.rb +77 -77
  61. data/lib/jekyll/liquid_renderer/table.rb +45 -55
  62. data/lib/jekyll/liquid_renderer.rb +80 -80
  63. data/lib/jekyll/log_adapter.rb +151 -151
  64. data/lib/jekyll/mime.types +939 -866
  65. data/lib/jekyll/page.rb +215 -217
  66. data/lib/jekyll/page_excerpt.rb +25 -25
  67. data/lib/jekyll/page_without_a_file.rb +14 -14
  68. data/lib/jekyll/path_manager.rb +74 -74
  69. data/lib/jekyll/plugin.rb +92 -92
  70. data/lib/jekyll/plugin_manager.rb +123 -115
  71. data/lib/jekyll/profiler.rb +51 -58
  72. data/lib/jekyll/publisher.rb +23 -23
  73. data/lib/jekyll/reader.rb +209 -192
  74. data/lib/jekyll/readers/collection_reader.rb +23 -23
  75. data/lib/jekyll/readers/data_reader.rb +113 -79
  76. data/lib/jekyll/readers/layout_reader.rb +62 -62
  77. data/lib/jekyll/readers/page_reader.rb +25 -25
  78. data/lib/jekyll/readers/post_reader.rb +85 -85
  79. data/lib/jekyll/readers/static_file_reader.rb +25 -25
  80. data/lib/jekyll/readers/theme_assets_reader.rb +52 -52
  81. data/lib/jekyll/regenerator.rb +195 -195
  82. data/lib/jekyll/related_posts.rb +52 -52
  83. data/lib/jekyll/renderer.rb +263 -265
  84. data/lib/jekyll/site.rb +576 -551
  85. data/lib/jekyll/static_file.rb +205 -208
  86. data/lib/jekyll/stevenson.rb +60 -60
  87. data/lib/jekyll/tags/highlight.rb +114 -110
  88. data/lib/jekyll/tags/include.rb +275 -275
  89. data/lib/jekyll/tags/link.rb +42 -42
  90. data/lib/jekyll/tags/post_url.rb +106 -106
  91. data/lib/jekyll/theme.rb +90 -86
  92. data/lib/jekyll/theme_builder.rb +121 -121
  93. data/lib/jekyll/url.rb +167 -167
  94. data/lib/jekyll/utils/ansi.rb +57 -57
  95. data/lib/jekyll/utils/exec.rb +26 -26
  96. data/lib/jekyll/utils/internet.rb +37 -37
  97. data/lib/jekyll/utils/platforms.rb +67 -67
  98. data/lib/jekyll/utils/thread_event.rb +31 -31
  99. data/lib/jekyll/utils/win_tz.rb +46 -75
  100. data/lib/jekyll/utils.rb +371 -367
  101. data/lib/jekyll/version.rb +5 -5
  102. data/lib/jekyll.rb +195 -195
  103. data/lib/site_template/.gitignore +5 -5
  104. data/lib/site_template/404.html +25 -25
  105. data/lib/site_template/_config.yml +55 -55
  106. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +29 -29
  107. data/lib/site_template/about.markdown +18 -18
  108. data/lib/site_template/index.markdown +6 -6
  109. data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -74
  110. data/lib/theme_template/Gemfile +4 -4
  111. data/lib/theme_template/LICENSE.txt.erb +21 -21
  112. data/lib/theme_template/README.md.erb +50 -52
  113. data/lib/theme_template/_layouts/default.html +1 -1
  114. data/lib/theme_template/_layouts/page.html +5 -5
  115. data/lib/theme_template/_layouts/post.html +5 -5
  116. data/lib/theme_template/example/_config.yml.erb +1 -1
  117. data/lib/theme_template/example/_post.md +12 -12
  118. data/lib/theme_template/example/index.html +14 -14
  119. data/lib/theme_template/example/style.scss +7 -7
  120. data/lib/theme_template/gitignore.erb +6 -6
  121. data/lib/theme_template/theme.gemspec.erb +16 -16
  122. data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -149
  123. data/rubocop/jekyll/no_p_allowed.rb +23 -23
  124. data/rubocop/jekyll/no_puts_allowed.rb +23 -23
  125. data/rubocop/jekyll.rb +5 -5
  126. metadata +64 -18
@@ -1,275 +1,275 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- module Tags
5
- class IncludeTag < Liquid::Tag
6
- VALID_SYNTAX = %r!
7
- ([\w-]+)\s*=\s*
8
- (?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w.-]+))
9
- !x.freeze
10
- VARIABLE_SYNTAX = %r!
11
- (?<variable>[^{]*(\{\{\s*[\w\-.]+\s*(\|.*)?\}\}[^\s{}]*)+)
12
- (?<params>.*)
13
- !mx.freeze
14
-
15
- FULL_VALID_SYNTAX = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z!.freeze
16
- VALID_FILENAME_CHARS = %r!^[\w/.-]+$!.freeze
17
- INVALID_SEQUENCES = %r![./]{2,}!.freeze
18
-
19
- def initialize(tag_name, markup, tokens)
20
- super
21
- markup = markup.strip
22
- matched = markup.match(VARIABLE_SYNTAX)
23
- if matched
24
- @file = matched["variable"].strip
25
- @params = matched["params"].strip
26
- else
27
- @file, @params = markup.split(%r!\s+!, 2)
28
- end
29
- validate_params if @params
30
- @tag_name = tag_name
31
- end
32
-
33
- def syntax_example
34
- "{% #{@tag_name} file.ext param='value' param2='value' %}"
35
- end
36
-
37
- def parse_params(context)
38
- params = {}
39
- @params.scan(VALID_SYNTAX) do |key, d_quoted, s_quoted, variable|
40
- value = if d_quoted
41
- d_quoted.include?('\\"') ? d_quoted.gsub('\\"', '"') : d_quoted
42
- elsif s_quoted
43
- s_quoted.include?("\\'") ? s_quoted.gsub("\\'", "'") : s_quoted
44
- elsif variable
45
- context[variable]
46
- end
47
-
48
- params[key] = value
49
- end
50
- params
51
- end
52
-
53
- def validate_file_name(file)
54
- if INVALID_SEQUENCES.match?(file) || !VALID_FILENAME_CHARS.match?(file)
55
- raise ArgumentError, <<~MSG
56
- Invalid syntax for include tag. File contains invalid characters or sequences:
57
-
58
- #{file}
59
-
60
- Valid syntax:
61
-
62
- #{syntax_example}
63
-
64
- MSG
65
- end
66
- end
67
-
68
- def validate_params
69
- unless FULL_VALID_SYNTAX.match?(@params)
70
- raise ArgumentError, <<~MSG
71
- Invalid syntax for include tag:
72
-
73
- #{@params}
74
-
75
- Valid syntax:
76
-
77
- #{syntax_example}
78
-
79
- MSG
80
- end
81
- end
82
-
83
- # Grab file read opts in the context
84
- def file_read_opts(context)
85
- context.registers[:site].file_read_opts
86
- end
87
-
88
- # Render the variable if required
89
- def render_variable(context)
90
- Liquid::Template.parse(@file).render(context) if VARIABLE_SYNTAX.match?(@file)
91
- end
92
-
93
- def tag_includes_dirs(context)
94
- context.registers[:site].includes_load_paths.freeze
95
- end
96
-
97
- def locate_include_file(context, file, safe)
98
- includes_dirs = tag_includes_dirs(context)
99
- includes_dirs.each do |dir|
100
- path = PathManager.join(dir, file)
101
- return path if valid_include_file?(path, dir.to_s, safe)
102
- end
103
- raise IOError, could_not_locate_message(file, includes_dirs, safe)
104
- end
105
-
106
- def render(context)
107
- site = context.registers[:site]
108
-
109
- file = render_variable(context) || @file
110
- validate_file_name(file)
111
-
112
- path = locate_include_file(context, file, site.safe)
113
- return unless path
114
-
115
- add_include_to_dependency(site, path, context)
116
-
117
- partial = load_cached_partial(path, context)
118
-
119
- context.stack do
120
- context["include"] = parse_params(context) if @params
121
- begin
122
- partial.render!(context)
123
- rescue Liquid::Error => e
124
- e.template_name = path
125
- e.markup_context = "included " if e.markup_context.nil?
126
- raise e
127
- end
128
- end
129
- end
130
-
131
- def add_include_to_dependency(site, path, context)
132
- if context.registers[:page]&.key?("path")
133
- site.regenerator.add_dependency(
134
- site.in_source_dir(context.registers[:page]["path"]),
135
- path
136
- )
137
- end
138
- end
139
-
140
- def load_cached_partial(path, context)
141
- context.registers[:cached_partials] ||= {}
142
- cached_partial = context.registers[:cached_partials]
143
-
144
- if cached_partial.key?(path)
145
- cached_partial[path]
146
- else
147
- unparsed_file = context.registers[:site]
148
- .liquid_renderer
149
- .file(path)
150
- begin
151
- cached_partial[path] = unparsed_file.parse(read_file(path, context))
152
- rescue Liquid::Error => e
153
- e.template_name = path
154
- e.markup_context = "included " if e.markup_context.nil?
155
- raise e
156
- end
157
- end
158
- end
159
-
160
- def valid_include_file?(path, dir, safe)
161
- !outside_site_source?(path, dir, safe) && File.file?(path)
162
- end
163
-
164
- def outside_site_source?(path, dir, safe)
165
- safe && !realpath_prefixed_with?(path, dir)
166
- end
167
-
168
- def realpath_prefixed_with?(path, dir)
169
- File.exist?(path) && File.realpath(path).start_with?(dir)
170
- rescue StandardError
171
- false
172
- end
173
-
174
- # This method allows to modify the file content by inheriting from the class.
175
- def read_file(file, context)
176
- File.read(file, **file_read_opts(context))
177
- end
178
-
179
- private
180
-
181
- def could_not_locate_message(file, includes_dirs, safe)
182
- message = "Could not locate the included file '#{file}' in any of "\
183
- "#{includes_dirs}. Ensure it exists in one of those directories and"
184
- message + if safe
185
- " is not a symlink as those are not allowed in safe mode."
186
- else
187
- ", if it is a symlink, does not point outside your site source."
188
- end
189
- end
190
- end
191
-
192
- # Do not inherit from this class.
193
- # TODO: Merge into the `Jekyll::Tags::IncludeTag` in v5.0
194
- class OptimizedIncludeTag < IncludeTag
195
- def render(context)
196
- @site ||= context.registers[:site]
197
-
198
- file = render_variable(context) || @file
199
- validate_file_name(file)
200
-
201
- @site.inclusions[file] ||= locate_include_file(file)
202
- inclusion = @site.inclusions[file]
203
-
204
- add_include_to_dependency(inclusion, context) if @site.config["incremental"]
205
-
206
- context.stack do
207
- context["include"] = parse_params(context) if @params
208
- inclusion.render(context)
209
- end
210
- end
211
-
212
- private
213
-
214
- def locate_include_file(file)
215
- @site.includes_load_paths.each do |dir|
216
- path = PathManager.join(dir, file)
217
- return Inclusion.new(@site, dir, file) if valid_include_file?(path, dir)
218
- end
219
- raise IOError, could_not_locate_message(file, @site.includes_load_paths, @site.safe)
220
- end
221
-
222
- def valid_include_file?(path, dir)
223
- File.file?(path) && !outside_scope?(path, dir)
224
- end
225
-
226
- def outside_scope?(path, dir)
227
- @site.safe && !realpath_prefixed_with?(path, dir)
228
- end
229
-
230
- def realpath_prefixed_with?(path, dir)
231
- File.realpath(path).start_with?(dir)
232
- rescue StandardError
233
- false
234
- end
235
-
236
- def add_include_to_dependency(inclusion, context)
237
- page = context.registers[:page]
238
- return unless page&.key?("path")
239
-
240
- absolute_path = \
241
- if page["collection"]
242
- @site.in_source_dir(@site.config["collections_dir"], page["path"])
243
- else
244
- @site.in_source_dir(page["path"])
245
- end
246
-
247
- @site.regenerator.add_dependency(absolute_path, inclusion.path)
248
- end
249
- end
250
-
251
- class IncludeRelativeTag < IncludeTag
252
- def tag_includes_dirs(context)
253
- Array(page_path(context)).freeze
254
- end
255
-
256
- def page_path(context)
257
- page, site = context.registers.values_at(:page, :site)
258
- return site.source unless page
259
-
260
- site.in_source_dir File.dirname(resource_path(page, site))
261
- end
262
-
263
- private
264
-
265
- def resource_path(page, site)
266
- path = page["path"]
267
- path = File.join(site.config["collections_dir"], path) if page["collection"]
268
- path.sub(%r!/#excerpt\z!, "")
269
- end
270
- end
271
- end
272
- end
273
-
274
- Liquid::Template.register_tag("include", Jekyll::Tags::OptimizedIncludeTag)
275
- Liquid::Template.register_tag("include_relative", Jekyll::Tags::IncludeRelativeTag)
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Tags
5
+ class IncludeTag < Liquid::Tag
6
+ VALID_SYNTAX = %r!
7
+ ([\w-]+)\s*=\s*
8
+ (?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w.-]+))
9
+ !x.freeze
10
+ VARIABLE_SYNTAX = %r!
11
+ (?<variable>[^{]*(\{\{\s*[\w\-.]+\s*(\|.*)?\}\}[^\s{}]*)+)
12
+ (?<params>.*)
13
+ !mx.freeze
14
+
15
+ FULL_VALID_SYNTAX = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z!.freeze
16
+ VALID_FILENAME_CHARS = %r!^[\w/.\-()+~\#@]+$!.freeze
17
+ INVALID_SEQUENCES = %r![./]{2,}!.freeze
18
+
19
+ def initialize(tag_name, markup, tokens)
20
+ super
21
+ markup = markup.strip
22
+ matched = markup.match(VARIABLE_SYNTAX)
23
+ if matched
24
+ @file = matched["variable"].strip
25
+ @params = matched["params"].strip
26
+ else
27
+ @file, @params = markup.split(%r!\s+!, 2)
28
+ end
29
+ validate_params if @params
30
+ @tag_name = tag_name
31
+ end
32
+
33
+ def syntax_example
34
+ "{% #{@tag_name} file.ext param='value' param2='value' %}"
35
+ end
36
+
37
+ def parse_params(context)
38
+ params = {}
39
+ @params.scan(VALID_SYNTAX) do |key, d_quoted, s_quoted, variable|
40
+ value = if d_quoted
41
+ d_quoted.include?('\\"') ? d_quoted.gsub('\\"', '"') : d_quoted
42
+ elsif s_quoted
43
+ s_quoted.include?("\\'") ? s_quoted.gsub("\\'", "'") : s_quoted
44
+ elsif variable
45
+ context[variable]
46
+ end
47
+
48
+ params[key] = value
49
+ end
50
+ params
51
+ end
52
+
53
+ def validate_file_name(file)
54
+ if INVALID_SEQUENCES.match?(file) || !VALID_FILENAME_CHARS.match?(file)
55
+ raise ArgumentError, <<~MSG
56
+ Invalid syntax for include tag. File contains invalid characters or sequences:
57
+
58
+ #{file}
59
+
60
+ Valid syntax:
61
+
62
+ #{syntax_example}
63
+
64
+ MSG
65
+ end
66
+ end
67
+
68
+ def validate_params
69
+ unless FULL_VALID_SYNTAX.match?(@params)
70
+ raise ArgumentError, <<~MSG
71
+ Invalid syntax for include tag:
72
+
73
+ #{@params}
74
+
75
+ Valid syntax:
76
+
77
+ #{syntax_example}
78
+
79
+ MSG
80
+ end
81
+ end
82
+
83
+ # Grab file read opts in the context
84
+ def file_read_opts(context)
85
+ context.registers[:site].file_read_opts
86
+ end
87
+
88
+ # Render the variable if required
89
+ def render_variable(context)
90
+ Liquid::Template.parse(@file).render(context) if VARIABLE_SYNTAX.match?(@file)
91
+ end
92
+
93
+ def tag_includes_dirs(context)
94
+ context.registers[:site].includes_load_paths.freeze
95
+ end
96
+
97
+ def locate_include_file(context, file, safe)
98
+ includes_dirs = tag_includes_dirs(context)
99
+ includes_dirs.each do |dir|
100
+ path = PathManager.join(dir, file)
101
+ return path if valid_include_file?(path, dir.to_s, safe)
102
+ end
103
+ raise IOError, could_not_locate_message(file, includes_dirs, safe)
104
+ end
105
+
106
+ def render(context)
107
+ site = context.registers[:site]
108
+
109
+ file = render_variable(context) || @file
110
+ validate_file_name(file)
111
+
112
+ path = locate_include_file(context, file, site.safe)
113
+ return unless path
114
+
115
+ add_include_to_dependency(site, path, context)
116
+
117
+ partial = load_cached_partial(path, context)
118
+
119
+ context.stack do
120
+ context["include"] = parse_params(context) if @params
121
+ begin
122
+ partial.render!(context)
123
+ rescue Liquid::Error => e
124
+ e.template_name = path
125
+ e.markup_context = "included " if e.markup_context.nil?
126
+ raise e
127
+ end
128
+ end
129
+ end
130
+
131
+ def add_include_to_dependency(site, path, context)
132
+ if context.registers[:page]&.key?("path")
133
+ site.regenerator.add_dependency(
134
+ site.in_source_dir(context.registers[:page]["path"]),
135
+ path
136
+ )
137
+ end
138
+ end
139
+
140
+ def load_cached_partial(path, context)
141
+ context.registers[:cached_partials] ||= {}
142
+ cached_partial = context.registers[:cached_partials]
143
+
144
+ if cached_partial.key?(path)
145
+ cached_partial[path]
146
+ else
147
+ unparsed_file = context.registers[:site]
148
+ .liquid_renderer
149
+ .file(path)
150
+ begin
151
+ cached_partial[path] = unparsed_file.parse(read_file(path, context))
152
+ rescue Liquid::Error => e
153
+ e.template_name = path
154
+ e.markup_context = "included " if e.markup_context.nil?
155
+ raise e
156
+ end
157
+ end
158
+ end
159
+
160
+ def valid_include_file?(path, dir, safe)
161
+ !outside_site_source?(path, dir, safe) && File.file?(path)
162
+ end
163
+
164
+ def outside_site_source?(path, dir, safe)
165
+ safe && !realpath_prefixed_with?(path, dir)
166
+ end
167
+
168
+ def realpath_prefixed_with?(path, dir)
169
+ File.exist?(path) && File.realpath(path).start_with?(dir)
170
+ rescue StandardError
171
+ false
172
+ end
173
+
174
+ # This method allows to modify the file content by inheriting from the class.
175
+ def read_file(file, context)
176
+ File.read(file, **file_read_opts(context))
177
+ end
178
+
179
+ private
180
+
181
+ def could_not_locate_message(file, includes_dirs, safe)
182
+ message = "Could not locate the included file '#{file}' in any of #{includes_dirs}. " \
183
+ "Ensure it exists in one of those directories and"
184
+ message + if safe
185
+ " is not a symlink as those are not allowed in safe mode."
186
+ else
187
+ ", if it is a symlink, does not point outside your site source."
188
+ end
189
+ end
190
+ end
191
+
192
+ # Do not inherit from this class.
193
+ # TODO: Merge into the `Jekyll::Tags::IncludeTag` in v5.0
194
+ class OptimizedIncludeTag < IncludeTag
195
+ def render(context)
196
+ @site ||= context.registers[:site]
197
+
198
+ file = render_variable(context) || @file
199
+ validate_file_name(file)
200
+
201
+ @site.inclusions[file] ||= locate_include_file(file)
202
+ inclusion = @site.inclusions[file]
203
+
204
+ add_include_to_dependency(inclusion, context) if @site.config["incremental"]
205
+
206
+ context.stack do
207
+ context["include"] = parse_params(context) if @params
208
+ inclusion.render(context)
209
+ end
210
+ end
211
+
212
+ private
213
+
214
+ def locate_include_file(file)
215
+ @site.includes_load_paths.each do |dir|
216
+ path = PathManager.join(dir, file)
217
+ return Inclusion.new(@site, dir, file) if valid_include_file?(path, dir)
218
+ end
219
+ raise IOError, could_not_locate_message(file, @site.includes_load_paths, @site.safe)
220
+ end
221
+
222
+ def valid_include_file?(path, dir)
223
+ File.file?(path) && !outside_scope?(path, dir)
224
+ end
225
+
226
+ def outside_scope?(path, dir)
227
+ @site.safe && !realpath_prefixed_with?(path, dir)
228
+ end
229
+
230
+ def realpath_prefixed_with?(path, dir)
231
+ File.realpath(path).start_with?(dir)
232
+ rescue StandardError
233
+ false
234
+ end
235
+
236
+ def add_include_to_dependency(inclusion, context)
237
+ page = context.registers[:page]
238
+ return unless page&.key?("path")
239
+
240
+ absolute_path = \
241
+ if page["collection"]
242
+ @site.in_source_dir(@site.config["collections_dir"], page["path"])
243
+ else
244
+ @site.in_source_dir(page["path"])
245
+ end
246
+
247
+ @site.regenerator.add_dependency(absolute_path, inclusion.path)
248
+ end
249
+ end
250
+
251
+ class IncludeRelativeTag < IncludeTag
252
+ def tag_includes_dirs(context)
253
+ Array(page_path(context)).freeze
254
+ end
255
+
256
+ def page_path(context)
257
+ page, site = context.registers.values_at(:page, :site)
258
+ return site.source unless page
259
+
260
+ site.in_source_dir File.dirname(resource_path(page, site))
261
+ end
262
+
263
+ private
264
+
265
+ def resource_path(page, site)
266
+ path = page["path"]
267
+ path = File.join(site.config["collections_dir"], path) if page["collection"]
268
+ path.delete_suffix("/#excerpt")
269
+ end
270
+ end
271
+ end
272
+ end
273
+
274
+ Liquid::Template.register_tag("include", Jekyll::Tags::OptimizedIncludeTag)
275
+ Liquid::Template.register_tag("include_relative", Jekyll::Tags::IncludeRelativeTag)
@@ -1,42 +1,42 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- module Tags
5
- class Link < Liquid::Tag
6
- include Jekyll::Filters::URLFilters
7
-
8
- class << self
9
- def tag_name
10
- name.split("::").last.downcase
11
- end
12
- end
13
-
14
- def initialize(tag_name, relative_path, tokens)
15
- super
16
-
17
- @relative_path = relative_path.strip
18
- end
19
-
20
- def render(context)
21
- @context = context
22
- site = context.registers[:site]
23
- relative_path = Liquid::Template.parse(@relative_path).render(context)
24
- relative_path_with_leading_slash = PathManager.join("", relative_path)
25
-
26
- site.each_site_file do |item|
27
- return relative_url(item) if item.relative_path == relative_path
28
- # This takes care of the case for static files that have a leading /
29
- return relative_url(item) if item.relative_path == relative_path_with_leading_slash
30
- end
31
-
32
- raise ArgumentError, <<~MSG
33
- Could not find document '#{relative_path}' in tag '#{self.class.tag_name}'.
34
-
35
- Make sure the document exists and the path is correct.
36
- MSG
37
- end
38
- end
39
- end
40
- end
41
-
42
- Liquid::Template.register_tag(Jekyll::Tags::Link.tag_name, Jekyll::Tags::Link)
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Tags
5
+ class Link < Liquid::Tag
6
+ include Jekyll::Filters::URLFilters
7
+
8
+ class << self
9
+ def tag_name
10
+ name.split("::").last.downcase
11
+ end
12
+ end
13
+
14
+ def initialize(tag_name, relative_path, tokens)
15
+ super
16
+
17
+ @relative_path = relative_path.strip
18
+ end
19
+
20
+ def render(context)
21
+ @context = context
22
+ site = context.registers[:site]
23
+ relative_path = Liquid::Template.parse(@relative_path).render(context)
24
+ relative_path_with_leading_slash = PathManager.join("", relative_path)
25
+
26
+ site.each_site_file do |item|
27
+ return relative_url(item) if item.relative_path == relative_path
28
+ # This takes care of the case for static files that have a leading /
29
+ return relative_url(item) if item.relative_path == relative_path_with_leading_slash
30
+ end
31
+
32
+ raise ArgumentError, <<~MSG
33
+ Could not find document '#{relative_path}' in tag '#{self.class.tag_name}'.
34
+
35
+ Make sure the document exists and the path is correct.
36
+ MSG
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ Liquid::Template.register_tag(Jekyll::Tags::Link.tag_name, Jekyll::Tags::Link)