Skip to content

Commit

Permalink
Remove the Renderer class by merging into GeneratedPage (#492)
Browse files Browse the repository at this point in the history
* Remove the `Renderer` class by merging into `GeneratedPage`

* DRY up conversions with the Transformable concern

* Clean up repo Gemfile

* Move yard to Gemfile top-level

* add return docs
  • Loading branch information
jaredcwhite authored Feb 18, 2022
1 parent 0d03040 commit 2715084
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 302 deletions.
12 changes: 1 addition & 11 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
source "https://rubygems.org"

gem "rake", "~> 13.0"
gem "yard", "~> 0.9"

group :development do
gem "solargraph"
end

#

group :test do
gem "cucumber", "~> 3.0"
gem "memory_profiler"
Expand All @@ -22,16 +21,7 @@ group :test do
gem "rubocop-bridgetown", "~> 0.3.0", require: false
gem "shoulda"
gem "simplecov"
end

#

group :bridgetown_optional_dependencies do
gem "liquid-c", "~> 4.0"
gem "mime-types", "~> 3.0"
gem "tomlrb", "~> 1.2"
gem "yajl-ruby", "~> 1.4"
gem "yard", "~> 0.9"
end

# Bridgetown
Expand Down
2 changes: 1 addition & 1 deletion bridgetown-core/lib/bridgetown-core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ module Bridgetown
autoload :Publishable, "bridgetown-core/concerns/publishable"
autoload :Publisher, "bridgetown-core/publisher"
autoload :Reader, "bridgetown-core/reader"
autoload :Renderer, "bridgetown-core/renderer"
autoload :RubyTemplateView, "bridgetown-core/ruby_template_view"
autoload :LogWriter, "bridgetown-core/log_writer"
autoload :Site, "bridgetown-core/site"
autoload :StaticFile, "bridgetown-core/static_file"
autoload :Transformable, "bridgetown-core/concerns/transformable"
autoload :URL, "bridgetown-core/url"
autoload :Utils, "bridgetown-core/utils"
autoload :VERSION, "bridgetown-core/version"
Expand Down
43 changes: 27 additions & 16 deletions bridgetown-core/lib/bridgetown-core/concerns/site/renderable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def render
Bridgetown::Hooks.trigger :site, :pre_render, self
execute_inline_ruby_for_layouts!
render_resources
render_generated_pages
generated_pages.each(&:transform!)
Bridgetown::Hooks.trigger :site, :post_render, self
end

Expand Down Expand Up @@ -46,6 +46,32 @@ def matched_converters_for_convertible(convertible)
matches
end

# @return [Array<Bridgetown::Layout>]
def validated_layouts_for(convertible, layout_name)
layout = layouts[layout_name]
warn_on_missing_layout convertible, layout, layout_name

layout_list = Set.new([layout])
while layout
layout_name = layout.data.layout
layout = layouts[layout_name]
warn_on_missing_layout convertible, layout, layout_name

layout_list << layout
end

layout_list.to_a.compact
end

def warn_on_missing_layout(convertible, layout, layout_name)
return unless layout.nil? && layout_name

Bridgetown.logger.warn(
"Build Warning:",
"Layout '#{layout_name}' requested via #{convertible.relative_path} does not exist."
)
end

# Renders all resources
# @return [void]
def render_resources
Expand All @@ -58,14 +84,6 @@ def render_resources
end
end

# Renders all generated pages
# @return [void]
def render_generated_pages
generated_pages.each do |page|
render_page page
end
end

# Renders a content item while ensuring site locale is set if the data is available.
# @param item [Document, Page, Bridgetown::Resource::Base] The item to render
# @yield Runs the block in between locale setting and resetting
Expand All @@ -80,12 +98,5 @@ def render_with_locale(item)
yield
end
end

# Regenerates a content item using {Renderer}
# @param item [Page] The page to render
# @return [void]
def render_page(page)
Bridgetown::Renderer.new(self, page).run
end
end
end
62 changes: 62 additions & 0 deletions bridgetown-core/lib/bridgetown-core/concerns/transformable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# frozen_string_literal: true

module Bridgetown
module Transformable
# Transforms an input document by running it through available converters
# (requires a `converter` method to be present on the including class)
#
# @param document [Bridgetown::GeneratedPage, Bridgetown::Resource::Base]
# @return String
# @yieldparam converter [Bridgetown::Converter]
# @yieldparam index [Integer] index of the conversion step
# @yieldparam output [String]
def transform_content(document)
converters.each_with_index.inject(document.content.to_s) do |content, (converter, index)|
output = if converter.method(:convert).arity == 1
converter.convert content
else
converter.convert content, document
end

yield converter, index, output if block_given?

output.html_safe
rescue StandardError => e
Bridgetown.logger.error "Conversion error:",
"#{converter.class} encountered an error while "\
"converting `#{document.relative_path}'"
raise e
end
end

# Transforms an input document by placing it within the specified layout
#
# @param layout [Bridgetown::Layout]
# @param output [String] the output from document content conversions
# @param document [Bridgetown::GeneratedPage, Bridgetown::Resource::Base]
# @return String
# @yieldparam converter [Bridgetown::Converter]
# @yieldparam layout_output [String]
def transform_with_layout(layout, output, document)
layout_converters = site.matched_converters_for_convertible(layout)
layout_input = layout.content.dup

layout_converters.inject(layout_input) do |content, converter|
next(content) unless [2, -2].include?(converter.method(:convert).arity) # rubocop:disable Performance/CollectionLiteralInLoop

layout.current_document = document
layout.current_document_output = output
layout_output = converter.convert content, layout

yield converter, layout_output if block_given?

layout_output
rescue StandardError => e
Bridgetown.logger.error "Conversion error:",
"#{converter.class} encountered an error while "\
"converting `#{document.relative_path}'"
raise e
end
end
end
end
98 changes: 81 additions & 17 deletions bridgetown-core/lib/bridgetown-core/generated_page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ class GeneratedPage
include LayoutPlaceable
include LiquidRenderable
include Publishable
include Transformable

attr_writer :dir
attr_accessor :site, :paginator, :name, :ext, :basename, :data, :content, :output

alias_method :extname, :ext

# A set of extensions that are considered HTML or HTML-like so we
# should not alter them, this includes .xhtml through XHTM5.
# should not alter them

HTML_EXTENSIONS = %w(
.html
Expand Down Expand Up @@ -54,11 +55,11 @@ def to_s
output || content || ""
end

# Accessor for data properties by Liquid.
# Accessor for data properties by Liquid
#
# property - The String name of the property to retrieve.
# @param property [String] name of the property to retrieve
#
# Returns the String value or nil if the property isn't included.
# @return [Object]
def [](property)
data[property]
end
Expand All @@ -67,7 +68,7 @@ def [](property)
# upon generation. This is derived from the permalink or, if
# permalink is absent, will be '/'
#
# Returns the String destination directory.
# @return [String]
def dir
if url.end_with?("/")
url
Expand All @@ -78,6 +79,8 @@ def dir
end

# Liquid representation of current page
#
# @return [Bridgetown::Drops::GeneratedPageDrop]
def to_liquid
@liquid_drop ||= Drops::GeneratedPageDrop.new(self)
end
Expand All @@ -90,7 +93,7 @@ def permalink

# The template of the permalink.
#
# Returns the template String.
# @return [String]
def template
if !html?
"/:path/:basename:output_ext"
Expand All @@ -103,7 +106,7 @@ def template

# The generated relative url of this page. e.g. /about.html.
#
# Returns the String url.
# @return [String]
def url
@url ||= URL.new(
template: template,
Expand All @@ -123,6 +126,22 @@ def url_placeholders
}
end

# Layout associated with this resource
# This will output a warning if the layout can't be found.
#
# @return [Bridgetown::Layout]
def layout
return @layout if @layout
return if no_layout?

@layout = site.layouts[data.layout].tap do |layout|
unless layout
Bridgetown.logger.warn "Generated Page:", "Layout '#{data.layout}' " \
"requested via #{relative_path} does not exist."
end
end
end

# Overide this in subclasses for custom initialization behavior
def process
# no-op by default
Expand All @@ -139,21 +158,68 @@ def relative_path
@relative_path ||= File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).delete_prefix("/")
end

# FIXME: spinning up a new Renderer object just to get an extension
# seems excessive
#
# The output extension of the page.
#
# Returns the output extension
# @return [String]
def output_ext
@output_ext ||= Bridgetown::Renderer.new(site, self).output_ext
@output_ext ||= (permalink_ext || converter_output_ext)
end

def permalink_ext
page_permalink = permalink
if page_permalink &&
!page_permalink.end_with?("/")
permalink_ext = File.extname(page_permalink)
permalink_ext unless permalink_ext.empty?
end
end

def converter_output_ext
if output_exts.size == 1
output_exts.last
else
output_exts[-2]
end
end

def output_exts
@output_exts ||= converters.filter_map do |c|
c.output_ext(extname)
end
end

# @return [Array<Bridgetown::Converter>]
def converters
@converters ||= site.matched_converters_for_convertible(self)
end

def transform!
Bridgetown.logger.debug "Transforming:", relative_path

trigger_hooks :pre_render
self.content = transform_content(self)
place_in_layout? ? place_into_layouts : self.output = content.dup
trigger_hooks :post_render

self
end

def place_into_layouts
Bridgetown.logger.debug "Placing in Layouts:", relative_path
rendered_output = content.dup

site.validated_layouts_for(self, data.layout).each do |layout|
rendered_output = transform_with_layout(layout, rendered_output, self)
end

self.output = rendered_output
end

# Obtain destination path.
#
# dest - The String path to the destination dir.
# @param dest [String] path to the destination dir
#
# Returns the destination file path String.
# @return [String]
def destination(dest)
path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index") if url.end_with?("/")
Expand All @@ -163,9 +229,7 @@ def destination(dest)

# Write the generated page file to the destination directory.
#
# dest - The String path to the destination dir.
#
# Returns nothing.
# @param dest [String] path to the destination dir
def write(dest)
path = destination(dest)
FileUtils.mkdir_p(File.dirname(path))
Expand Down
Loading

0 comments on commit 2715084

Please sign in to comment.