jekyll 4.2.1 → 4.2.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 (124) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +350 -350
  3. data/LICENSE +21 -21
  4. data/README.markdown +86 -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 +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 +190 -190
  12. data/lib/jekyll/cleaner.rb +111 -111
  13. data/lib/jekyll/collection.rb +309 -309
  14. data/lib/jekyll/command.rb +105 -105
  15. data/lib/jekyll/commands/build.rb +93 -93
  16. data/lib/jekyll/commands/clean.rb +45 -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 +172 -169
  20. data/lib/jekyll/commands/new_theme.rb +40 -40
  21. data/lib/jekyll/commands/serve/live_reload_reactor.rb +122 -122
  22. data/lib/jekyll/commands/serve/livereload_assets/livereload.js +1183 -1183
  23. data/lib/jekyll/commands/serve/servlet.rb +202 -202
  24. data/lib/jekyll/commands/serve/websockets.rb +81 -81
  25. data/lib/jekyll/commands/serve.rb +362 -362
  26. data/lib/jekyll/configuration.rb +313 -313
  27. data/lib/jekyll/converter.rb +54 -54
  28. data/lib/jekyll/converters/identity.rb +41 -41
  29. data/lib/jekyll/converters/markdown/kramdown_parser.rb +199 -199
  30. data/lib/jekyll/converters/markdown.rb +113 -113
  31. data/lib/jekyll/converters/smartypants.rb +70 -70
  32. data/lib/jekyll/convertible.rb +257 -257
  33. data/lib/jekyll/deprecator.rb +50 -50
  34. data/lib/jekyll/document.rb +544 -544
  35. data/lib/jekyll/drops/collection_drop.rb +20 -20
  36. data/lib/jekyll/drops/document_drop.rb +70 -70
  37. data/lib/jekyll/drops/drop.rb +293 -293
  38. data/lib/jekyll/drops/excerpt_drop.rb +19 -19
  39. data/lib/jekyll/drops/jekyll_drop.rb +32 -32
  40. data/lib/jekyll/drops/site_drop.rb +66 -66
  41. data/lib/jekyll/drops/static_file_drop.rb +14 -14
  42. data/lib/jekyll/drops/unified_payload_drop.rb +26 -26
  43. data/lib/jekyll/drops/url_drop.rb +140 -140
  44. data/lib/jekyll/entry_filter.rb +121 -121
  45. data/lib/jekyll/errors.rb +20 -20
  46. data/lib/jekyll/excerpt.rb +201 -201
  47. data/lib/jekyll/external.rb +79 -79
  48. data/lib/jekyll/filters/date_filters.rb +110 -110
  49. data/lib/jekyll/filters/grouping_filters.rb +64 -64
  50. data/lib/jekyll/filters/url_filters.rb +98 -98
  51. data/lib/jekyll/filters.rb +535 -535
  52. data/lib/jekyll/frontmatter_defaults.rb +240 -240
  53. data/lib/jekyll/generator.rb +5 -5
  54. data/lib/jekyll/hooks.rb +107 -107
  55. data/lib/jekyll/inclusion.rb +32 -32
  56. data/lib/jekyll/layout.rb +67 -67
  57. data/lib/jekyll/liquid_extensions.rb +22 -22
  58. data/lib/jekyll/liquid_renderer/file.rb +77 -77
  59. data/lib/jekyll/liquid_renderer/table.rb +55 -55
  60. data/lib/jekyll/liquid_renderer.rb +80 -80
  61. data/lib/jekyll/log_adapter.rb +151 -151
  62. data/lib/jekyll/mime.types +866 -866
  63. data/lib/jekyll/page.rb +217 -217
  64. data/lib/jekyll/page_excerpt.rb +25 -25
  65. data/lib/jekyll/page_without_a_file.rb +14 -14
  66. data/lib/jekyll/path_manager.rb +74 -74
  67. data/lib/jekyll/plugin.rb +92 -92
  68. data/lib/jekyll/plugin_manager.rb +115 -115
  69. data/lib/jekyll/profiler.rb +58 -58
  70. data/lib/jekyll/publisher.rb +23 -23
  71. data/lib/jekyll/reader.rb +192 -192
  72. data/lib/jekyll/readers/collection_reader.rb +23 -23
  73. data/lib/jekyll/readers/data_reader.rb +79 -79
  74. data/lib/jekyll/readers/layout_reader.rb +62 -62
  75. data/lib/jekyll/readers/page_reader.rb +25 -25
  76. data/lib/jekyll/readers/post_reader.rb +85 -85
  77. data/lib/jekyll/readers/static_file_reader.rb +25 -25
  78. data/lib/jekyll/readers/theme_assets_reader.rb +52 -52
  79. data/lib/jekyll/regenerator.rb +195 -195
  80. data/lib/jekyll/related_posts.rb +52 -52
  81. data/lib/jekyll/renderer.rb +265 -265
  82. data/lib/jekyll/site.rb +551 -551
  83. data/lib/jekyll/static_file.rb +208 -208
  84. data/lib/jekyll/stevenson.rb +60 -60
  85. data/lib/jekyll/tags/highlight.rb +110 -110
  86. data/lib/jekyll/tags/include.rb +275 -275
  87. data/lib/jekyll/tags/link.rb +42 -42
  88. data/lib/jekyll/tags/post_url.rb +106 -106
  89. data/lib/jekyll/theme.rb +86 -86
  90. data/lib/jekyll/theme_builder.rb +121 -121
  91. data/lib/jekyll/url.rb +167 -167
  92. data/lib/jekyll/utils/ansi.rb +57 -57
  93. data/lib/jekyll/utils/exec.rb +26 -26
  94. data/lib/jekyll/utils/internet.rb +37 -37
  95. data/lib/jekyll/utils/platforms.rb +67 -67
  96. data/lib/jekyll/utils/thread_event.rb +31 -31
  97. data/lib/jekyll/utils/win_tz.rb +75 -75
  98. data/lib/jekyll/utils.rb +367 -367
  99. data/lib/jekyll/version.rb +5 -5
  100. data/lib/jekyll.rb +195 -195
  101. data/lib/site_template/.gitignore +5 -5
  102. data/lib/site_template/404.html +25 -25
  103. data/lib/site_template/_config.yml +55 -55
  104. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +29 -29
  105. data/lib/site_template/about.markdown +18 -18
  106. data/lib/site_template/index.markdown +6 -6
  107. data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -74
  108. data/lib/theme_template/Gemfile +4 -4
  109. data/lib/theme_template/LICENSE.txt.erb +21 -21
  110. data/lib/theme_template/README.md.erb +52 -52
  111. data/lib/theme_template/_layouts/default.html +1 -1
  112. data/lib/theme_template/_layouts/page.html +5 -5
  113. data/lib/theme_template/_layouts/post.html +5 -5
  114. data/lib/theme_template/example/_config.yml.erb +1 -1
  115. data/lib/theme_template/example/_post.md +12 -12
  116. data/lib/theme_template/example/index.html +14 -14
  117. data/lib/theme_template/example/style.scss +7 -7
  118. data/lib/theme_template/gitignore.erb +6 -6
  119. data/lib/theme_template/theme.gemspec.erb +16 -16
  120. data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -149
  121. data/rubocop/jekyll/no_p_allowed.rb +23 -23
  122. data/rubocop/jekyll/no_puts_allowed.rb +23 -23
  123. data/rubocop/jekyll.rb +5 -5
  124. metadata +3 -3
@@ -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 "\
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,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)