jekyll 4.2.0 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +350 -347
  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 +169 -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 -365
  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 -260
  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 -270
  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,265 +1,265 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- class Renderer
5
- attr_reader :document, :site
6
- attr_writer :layouts, :payload
7
-
8
- def initialize(site, document, site_payload = nil)
9
- @site = site
10
- @document = document
11
- @payload = site_payload
12
- @layouts = nil
13
- end
14
-
15
- # Fetches the payload used in Liquid rendering.
16
- # It can be written with #payload=(new_payload)
17
- # Falls back to site.site_payload if no payload is set.
18
- #
19
- # Returns a Jekyll::Drops::UnifiedPayloadDrop
20
- def payload
21
- @payload ||= site.site_payload
22
- end
23
-
24
- # The list of layouts registered for this Renderer.
25
- # It can be written with #layouts=(new_layouts)
26
- # Falls back to site.layouts if no layouts are registered.
27
- #
28
- # Returns a Hash of String => Jekyll::Layout identified
29
- # as basename without the extension name.
30
- def layouts
31
- @layouts || site.layouts
32
- end
33
-
34
- # Determine which converters to use based on this document's
35
- # extension.
36
- #
37
- # Returns Array of Converter instances.
38
- def converters
39
- @converters ||= site.converters.select { |c| c.matches(document.extname) }.tap(&:sort!)
40
- end
41
-
42
- # Determine the extname the outputted file should have
43
- #
44
- # Returns String the output extname including the leading period.
45
- def output_ext
46
- @output_ext ||= (permalink_ext || converter_output_ext)
47
- end
48
-
49
- # Prepare payload and render the document
50
- #
51
- # Returns String rendered document output
52
- def run
53
- Jekyll.logger.debug "Rendering:", document.relative_path
54
-
55
- assign_pages!
56
- assign_current_document!
57
- assign_highlighter_options!
58
- assign_layout_data!
59
-
60
- Jekyll.logger.debug "Pre-Render Hooks:", document.relative_path
61
- document.trigger_hooks(:pre_render, payload)
62
-
63
- render_document
64
- end
65
-
66
- # Render the document.
67
- #
68
- # Returns String rendered document output
69
- # rubocop: disable Metrics/AbcSize, Metrics/MethodLength
70
- def render_document
71
- info = {
72
- :registers => { :site => site, :page => payload["page"] },
73
- :strict_filters => liquid_options["strict_filters"],
74
- :strict_variables => liquid_options["strict_variables"],
75
- }
76
-
77
- output = document.content
78
- if document.render_with_liquid?
79
- Jekyll.logger.debug "Rendering Liquid:", document.relative_path
80
- output = render_liquid(output, payload, info, document.path)
81
- end
82
-
83
- Jekyll.logger.debug "Rendering Markup:", document.relative_path
84
- output = convert(output.to_s)
85
- document.content = output
86
-
87
- Jekyll.logger.debug "Post-Convert Hooks:", document.relative_path
88
- document.trigger_hooks(:post_convert)
89
- output = document.content
90
-
91
- if document.place_in_layout?
92
- Jekyll.logger.debug "Rendering Layout:", document.relative_path
93
- output = place_in_layouts(output, payload, info)
94
- end
95
-
96
- output
97
- end
98
- # rubocop: enable Metrics/AbcSize, Metrics/MethodLength
99
-
100
- # Convert the document using the converters which match this renderer's document.
101
- #
102
- # Returns String the converted content.
103
- def convert(content)
104
- converters.reduce(content) do |output, converter|
105
- begin
106
- converter.convert output
107
- rescue StandardError => e
108
- Jekyll.logger.error "Conversion error:",
109
- "#{converter.class} encountered an error while "\
110
- "converting '#{document.relative_path}':"
111
- Jekyll.logger.error("", e.to_s)
112
- raise e
113
- end
114
- end
115
- end
116
-
117
- # Render the given content with the payload and info
118
- #
119
- # content -
120
- # payload -
121
- # info -
122
- # path - (optional) the path to the file, for use in ex
123
- #
124
- # Returns String the content, rendered by Liquid.
125
- def render_liquid(content, payload, info, path = nil)
126
- template = site.liquid_renderer.file(path).parse(content)
127
- template.warnings.each do |e|
128
- Jekyll.logger.warn "Liquid Warning:",
129
- LiquidRenderer.format_error(e, path || document.relative_path)
130
- end
131
- template.render!(payload, info)
132
- # rubocop: disable Lint/RescueException
133
- rescue Exception => e
134
- Jekyll.logger.error "Liquid Exception:",
135
- LiquidRenderer.format_error(e, path || document.relative_path)
136
- raise e
137
- end
138
- # rubocop: enable Lint/RescueException
139
-
140
- # Checks if the layout specified in the document actually exists
141
- #
142
- # layout - the layout to check
143
- #
144
- # Returns Boolean true if the layout is invalid, false if otherwise
145
- def invalid_layout?(layout)
146
- !document.data["layout"].nil? && layout.nil? && !(document.is_a? Jekyll::Excerpt)
147
- end
148
-
149
- # Render layouts and place document content inside.
150
- #
151
- # Returns String rendered content
152
- def place_in_layouts(content, payload, info)
153
- output = content.dup
154
- layout = layouts[document.data["layout"].to_s]
155
- validate_layout(layout)
156
-
157
- used = Set.new([layout])
158
-
159
- # Reset the payload layout data to ensure it starts fresh for each page.
160
- payload["layout"] = nil
161
-
162
- while layout
163
- output = render_layout(output, layout, info)
164
- add_regenerator_dependencies(layout)
165
-
166
- next unless (layout = site.layouts[layout.data["layout"]])
167
- break if used.include?(layout)
168
-
169
- used << layout
170
- end
171
- output
172
- end
173
-
174
- private
175
-
176
- # Checks if the layout specified in the document actually exists
177
- #
178
- # layout - the layout to check
179
- # Returns nothing
180
- def validate_layout(layout)
181
- return unless invalid_layout?(layout)
182
-
183
- Jekyll.logger.warn "Build Warning:", "Layout '#{document.data["layout"]}' requested " \
184
- "in #{document.relative_path} does not exist."
185
- end
186
-
187
- # Render layout content into document.output
188
- #
189
- # Returns String rendered content
190
- def render_layout(output, layout, info)
191
- payload["content"] = output
192
- payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
193
-
194
- render_liquid(
195
- layout.content,
196
- payload,
197
- info,
198
- layout.path
199
- )
200
- end
201
-
202
- def add_regenerator_dependencies(layout)
203
- return unless document.write?
204
-
205
- site.regenerator.add_dependency(
206
- site.in_source_dir(document.path),
207
- layout.path
208
- )
209
- end
210
-
211
- # Set page content to payload and assign pager if document has one.
212
- #
213
- # Returns nothing
214
- def assign_pages!
215
- payload["page"] = document.to_liquid
216
- payload["paginator"] = (document.pager.to_liquid if document.respond_to?(:pager))
217
- end
218
-
219
- # Set related posts to payload if document is a post.
220
- #
221
- # Returns nothing
222
- def assign_current_document!
223
- payload["site"].current_document = document
224
- end
225
-
226
- # Set highlighter prefix and suffix
227
- #
228
- # Returns nothing
229
- def assign_highlighter_options!
230
- payload["highlighter_prefix"] = converters.first.highlighter_prefix
231
- payload["highlighter_suffix"] = converters.first.highlighter_suffix
232
- end
233
-
234
- def assign_layout_data!
235
- layout = layouts[document.data["layout"]]
236
- payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {}) if layout
237
- end
238
-
239
- def permalink_ext
240
- document_permalink = document.permalink
241
- if document_permalink && !document_permalink.end_with?("/")
242
- permalink_ext = File.extname(document_permalink)
243
- permalink_ext unless permalink_ext.empty?
244
- end
245
- end
246
-
247
- def converter_output_ext
248
- if output_exts.size == 1
249
- output_exts.last
250
- else
251
- output_exts[-2]
252
- end
253
- end
254
-
255
- def output_exts
256
- @output_exts ||= converters.map do |c|
257
- c.output_ext(document.extname)
258
- end.tap(&:compact!)
259
- end
260
-
261
- def liquid_options
262
- @liquid_options ||= site.config["liquid"]
263
- end
264
- end
265
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class Renderer
5
+ attr_reader :document, :site
6
+ attr_writer :layouts, :payload
7
+
8
+ def initialize(site, document, site_payload = nil)
9
+ @site = site
10
+ @document = document
11
+ @payload = site_payload
12
+ @layouts = nil
13
+ end
14
+
15
+ # Fetches the payload used in Liquid rendering.
16
+ # It can be written with #payload=(new_payload)
17
+ # Falls back to site.site_payload if no payload is set.
18
+ #
19
+ # Returns a Jekyll::Drops::UnifiedPayloadDrop
20
+ def payload
21
+ @payload ||= site.site_payload
22
+ end
23
+
24
+ # The list of layouts registered for this Renderer.
25
+ # It can be written with #layouts=(new_layouts)
26
+ # Falls back to site.layouts if no layouts are registered.
27
+ #
28
+ # Returns a Hash of String => Jekyll::Layout identified
29
+ # as basename without the extension name.
30
+ def layouts
31
+ @layouts || site.layouts
32
+ end
33
+
34
+ # Determine which converters to use based on this document's
35
+ # extension.
36
+ #
37
+ # Returns Array of Converter instances.
38
+ def converters
39
+ @converters ||= site.converters.select { |c| c.matches(document.extname) }.tap(&:sort!)
40
+ end
41
+
42
+ # Determine the extname the outputted file should have
43
+ #
44
+ # Returns String the output extname including the leading period.
45
+ def output_ext
46
+ @output_ext ||= (permalink_ext || converter_output_ext)
47
+ end
48
+
49
+ # Prepare payload and render the document
50
+ #
51
+ # Returns String rendered document output
52
+ def run
53
+ Jekyll.logger.debug "Rendering:", document.relative_path
54
+
55
+ assign_pages!
56
+ assign_current_document!
57
+ assign_highlighter_options!
58
+ assign_layout_data!
59
+
60
+ Jekyll.logger.debug "Pre-Render Hooks:", document.relative_path
61
+ document.trigger_hooks(:pre_render, payload)
62
+
63
+ render_document
64
+ end
65
+
66
+ # Render the document.
67
+ #
68
+ # Returns String rendered document output
69
+ # rubocop: disable Metrics/AbcSize, Metrics/MethodLength
70
+ def render_document
71
+ info = {
72
+ :registers => { :site => site, :page => payload["page"] },
73
+ :strict_filters => liquid_options["strict_filters"],
74
+ :strict_variables => liquid_options["strict_variables"],
75
+ }
76
+
77
+ output = document.content
78
+ if document.render_with_liquid?
79
+ Jekyll.logger.debug "Rendering Liquid:", document.relative_path
80
+ output = render_liquid(output, payload, info, document.path)
81
+ end
82
+
83
+ Jekyll.logger.debug "Rendering Markup:", document.relative_path
84
+ output = convert(output.to_s)
85
+ document.content = output
86
+
87
+ Jekyll.logger.debug "Post-Convert Hooks:", document.relative_path
88
+ document.trigger_hooks(:post_convert)
89
+ output = document.content
90
+
91
+ if document.place_in_layout?
92
+ Jekyll.logger.debug "Rendering Layout:", document.relative_path
93
+ output = place_in_layouts(output, payload, info)
94
+ end
95
+
96
+ output
97
+ end
98
+ # rubocop: enable Metrics/AbcSize, Metrics/MethodLength
99
+
100
+ # Convert the document using the converters which match this renderer's document.
101
+ #
102
+ # Returns String the converted content.
103
+ def convert(content)
104
+ converters.reduce(content) do |output, converter|
105
+ begin
106
+ converter.convert output
107
+ rescue StandardError => e
108
+ Jekyll.logger.error "Conversion error:",
109
+ "#{converter.class} encountered an error while "\
110
+ "converting '#{document.relative_path}':"
111
+ Jekyll.logger.error("", e.to_s)
112
+ raise e
113
+ end
114
+ end
115
+ end
116
+
117
+ # Render the given content with the payload and info
118
+ #
119
+ # content -
120
+ # payload -
121
+ # info -
122
+ # path - (optional) the path to the file, for use in ex
123
+ #
124
+ # Returns String the content, rendered by Liquid.
125
+ def render_liquid(content, payload, info, path = nil)
126
+ template = site.liquid_renderer.file(path).parse(content)
127
+ template.warnings.each do |e|
128
+ Jekyll.logger.warn "Liquid Warning:",
129
+ LiquidRenderer.format_error(e, path || document.relative_path)
130
+ end
131
+ template.render!(payload, info)
132
+ # rubocop: disable Lint/RescueException
133
+ rescue Exception => e
134
+ Jekyll.logger.error "Liquid Exception:",
135
+ LiquidRenderer.format_error(e, path || document.relative_path)
136
+ raise e
137
+ end
138
+ # rubocop: enable Lint/RescueException
139
+
140
+ # Checks if the layout specified in the document actually exists
141
+ #
142
+ # layout - the layout to check
143
+ #
144
+ # Returns Boolean true if the layout is invalid, false if otherwise
145
+ def invalid_layout?(layout)
146
+ !document.data["layout"].nil? && layout.nil? && !(document.is_a? Jekyll::Excerpt)
147
+ end
148
+
149
+ # Render layouts and place document content inside.
150
+ #
151
+ # Returns String rendered content
152
+ def place_in_layouts(content, payload, info)
153
+ output = content.dup
154
+ layout = layouts[document.data["layout"].to_s]
155
+ validate_layout(layout)
156
+
157
+ used = Set.new([layout])
158
+
159
+ # Reset the payload layout data to ensure it starts fresh for each page.
160
+ payload["layout"] = nil
161
+
162
+ while layout
163
+ output = render_layout(output, layout, info)
164
+ add_regenerator_dependencies(layout)
165
+
166
+ next unless (layout = site.layouts[layout.data["layout"]])
167
+ break if used.include?(layout)
168
+
169
+ used << layout
170
+ end
171
+ output
172
+ end
173
+
174
+ private
175
+
176
+ # Checks if the layout specified in the document actually exists
177
+ #
178
+ # layout - the layout to check
179
+ # Returns nothing
180
+ def validate_layout(layout)
181
+ return unless invalid_layout?(layout)
182
+
183
+ Jekyll.logger.warn "Build Warning:", "Layout '#{document.data["layout"]}' requested " \
184
+ "in #{document.relative_path} does not exist."
185
+ end
186
+
187
+ # Render layout content into document.output
188
+ #
189
+ # Returns String rendered content
190
+ def render_layout(output, layout, info)
191
+ payload["content"] = output
192
+ payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
193
+
194
+ render_liquid(
195
+ layout.content,
196
+ payload,
197
+ info,
198
+ layout.path
199
+ )
200
+ end
201
+
202
+ def add_regenerator_dependencies(layout)
203
+ return unless document.write?
204
+
205
+ site.regenerator.add_dependency(
206
+ site.in_source_dir(document.path),
207
+ layout.path
208
+ )
209
+ end
210
+
211
+ # Set page content to payload and assign pager if document has one.
212
+ #
213
+ # Returns nothing
214
+ def assign_pages!
215
+ payload["page"] = document.to_liquid
216
+ payload["paginator"] = (document.pager.to_liquid if document.respond_to?(:pager))
217
+ end
218
+
219
+ # Set related posts to payload if document is a post.
220
+ #
221
+ # Returns nothing
222
+ def assign_current_document!
223
+ payload["site"].current_document = document
224
+ end
225
+
226
+ # Set highlighter prefix and suffix
227
+ #
228
+ # Returns nothing
229
+ def assign_highlighter_options!
230
+ payload["highlighter_prefix"] = converters.first.highlighter_prefix
231
+ payload["highlighter_suffix"] = converters.first.highlighter_suffix
232
+ end
233
+
234
+ def assign_layout_data!
235
+ layout = layouts[document.data["layout"]]
236
+ payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {}) if layout
237
+ end
238
+
239
+ def permalink_ext
240
+ document_permalink = document.permalink
241
+ if document_permalink && !document_permalink.end_with?("/")
242
+ permalink_ext = File.extname(document_permalink)
243
+ permalink_ext unless permalink_ext.empty?
244
+ end
245
+ end
246
+
247
+ def converter_output_ext
248
+ if output_exts.size == 1
249
+ output_exts.last
250
+ else
251
+ output_exts[-2]
252
+ end
253
+ end
254
+
255
+ def output_exts
256
+ @output_exts ||= converters.map do |c|
257
+ c.output_ext(document.extname)
258
+ end.tap(&:compact!)
259
+ end
260
+
261
+ def liquid_options
262
+ @liquid_options ||= site.config["liquid"]
263
+ end
264
+ end
265
+ end