diff --git a/.rubocop.yml b/.rubocop.yml index 8ae01fb1..787fbdbe 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,7 +4,6 @@ AllCops: Include: - lib/**/*.rb Exclude: - - lib/jekyll/convertible.rb - lib/jekyll/renderer.rb - bin/**/* - benchmark/**/* diff --git a/lib/jekyll/convertible.rb b/lib/jekyll/convertible.rb index ca613f78..65052b68 100644 --- a/lib/jekyll/convertible.rb +++ b/lib/jekyll/convertible.rb @@ -35,6 +35,7 @@ module Jekyll # opts - optional parameter to File.read, default at site configs # # Returns nothing. + # rubocop:disable Metrics/AbcSize def read_yaml(base, name, opts = {}) filename = File.join(base, name) @@ -58,6 +59,7 @@ module Jekyll self.data end + # rubocop:enable Metrics/AbcSize def validate_data!(filename) unless self.data.is_a?(Hash) @@ -76,18 +78,7 @@ module Jekyll # # Returns the transformed contents. def transform - converters.reduce(content) do |output, converter| - begin - converter.convert output - rescue => e - Jekyll.logger.error( - "Conversion error:", - "#{converter.class} encountered an error while converting '#{path}':" - ) - Jekyll.logger.error("", e.to_s) - raise e - end - end + _renderer.transform end # Determine the extension depending on content_type. @@ -95,7 +86,7 @@ module Jekyll # Returns the String extension for the output file. # e.g. ".html" for an HTML output file. def output_ext - Jekyll::Renderer.new(site, self).output_ext + _renderer.output_ext end # Determine which converter to use based on this convertible's @@ -103,7 +94,7 @@ module Jekyll # # Returns the Converter instance. def converters - @converters ||= site.converters.select { |c| c.matches(ext) }.sort + _renderer.converters end # Render Liquid in the content @@ -114,17 +105,7 @@ module Jekyll # # Returns the converted content def render_liquid(content, payload, info, path) - template = site.liquid_renderer.file(path).parse(content) - template.warnings.each do |e| - Jekyll.logger.warn "Liquid Warning:", - LiquidRenderer.format_error(e, path || self.path) - end - template.render!(payload, info) - # rubocop: disable RescueException - rescue Exception => e - Jekyll.logger.error "Liquid Exception:", - LiquidRenderer.format_error(e, path || self.path) - raise e + _renderer.render_liquid(content, payload, info, path) end # rubocop: enable RescueException @@ -211,40 +192,10 @@ module Jekyll # # Returns nothing def render_all_layouts(layouts, payload, info) - # recursively render layouts - layout = layouts[data["layout"]] - - Jekyll.logger.warn( - "Build Warning:", - "Layout '#{data["layout"]}' requested in #{path} does not exist." - ) if invalid_layout? layout - - used = Set.new([layout]) - - # Reset the payload layout data to ensure it starts fresh for each page. - payload["layout"] = nil - - while layout - Jekyll.logger.debug "Rendering Layout:", path - payload["content"] = output - payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {}) - - self.output = render_liquid(layout.content, - payload, - info, - layout.relative_path) - - # Add layout to dependency tree - site.regenerator.add_dependency( - site.in_source_dir(path), - site.in_source_dir(layout.path) - ) - - if (layout = layouts[layout.data["layout"]]) - break if used.include?(layout) - used << layout - end - end + _renderer.layouts = layouts + _renderer.place_in_layouts(output, payload, info) + ensure + @_renderer = nil # this will allow the modifications above to disappear end # Add any necessary layouts to this convertible document. @@ -254,32 +205,16 @@ module Jekyll # # Returns nothing. def do_layout(payload, layouts) - Jekyll.logger.debug "Rendering:", self.relative_path - - Jekyll.logger.debug "Pre-Render Hooks:", self.relative_path - Jekyll::Hooks.trigger hook_owner, :pre_render, self, payload - info = { - :filters => [Jekyll::Filters], - :registers => { :site => site, :page => payload["page"] } - } - - # render and transform content (this becomes the final content of the object) - payload["highlighter_prefix"] = converters.first.highlighter_prefix - payload["highlighter_suffix"] = converters.first.highlighter_suffix - - if render_with_liquid? - Jekyll.logger.debug "Rendering Liquid:", self.relative_path - self.content = render_liquid(content, payload, info, path) + _renderer.tap do |renderer| + renderer.layouts = layouts + renderer.payload = payload + renderer.run end - Jekyll.logger.debug "Rendering Markup:", self.relative_path - self.content = transform - # output keeps track of what will finally be written - self.output = content - - render_all_layouts(layouts, payload, info) if place_in_layout? Jekyll.logger.debug "Post-Render Hooks:", self.relative_path Jekyll::Hooks.trigger hook_owner, :post_render, self + ensure + @_renderer = nil # this will allow the modifications above to disappear end # Write the generated page file to the destination directory. @@ -306,5 +241,10 @@ module Jekyll data[property] end end + + private + def _renderer + @_renderer ||= Jekyll::Renderer.new(site, self) + end end end diff --git a/lib/jekyll/renderer.rb b/lib/jekyll/renderer.rb index 083a2a6b..749882bf 100644 --- a/lib/jekyll/renderer.rb +++ b/lib/jekyll/renderer.rb @@ -2,12 +2,32 @@ module Jekyll class Renderer - attr_reader :document, :site, :payload + attr_reader :document, :site + attr_writer :layouts, :payload def initialize(site, document, site_payload = nil) @site = site @document = document - @payload = site_payload || site.site_payload + @payload = site_payload + end + + # Fetches the payload used in Liquid rendering. + # It can be written with #payload=(new_payload) + # Falls back to site.site_payload if no payload is set. + # + # Returns a Jekyll::Drops::UnifiedPayloadDrop + def payload + @payload ||= site.site_payload + end + + # The list of layouts registered for this Renderer. + # It can be written with #layouts=(new_layouts) + # Falls back to site.layouts if no layouts are registered. + # + # Returns a Hash of String => Jekyll::Layout identified + # as basename without the extension name. + def layouts + @layouts || site.layouts end # Determine which converters to use based on this document's @@ -15,7 +35,7 @@ module Jekyll # # Returns an array of Converter instances. def converters - @converters ||= site.converters.select { |c| c.matches(document.extname) } + @converters ||= site.converters.select { |c| c.matches(document.extname) }.sort end # Determine the extname the outputted file should have @@ -126,7 +146,7 @@ module Jekyll # # Returns true if the layout is invalid, false if otherwise def invalid_layout?(layout) - !document.data["layout"].nil? && layout.nil? + !document.data["layout"].nil? && layout.nil? && !(document.is_a? Jekyll::Excerpt) end # Render layouts and place given content inside. @@ -137,7 +157,7 @@ module Jekyll # Returns the content placed in the Liquid-rendered layouts def place_in_layouts(content, payload, info) output = content.dup - layout = site.layouts[document.data["layout"]] + layout = layouts[document.data["layout"]] Jekyll.logger.warn( "Build Warning:", @@ -167,7 +187,7 @@ module Jekyll site.in_source_dir(layout.path) ) if document.write? - if (layout = site.layouts[layout.data["layout"]]) + if (layout = layouts[layout.data["layout"]]) break if used.include?(layout) used << layout end