# frozen_string_literal: true require_relative "errors" module Hanami class View # @api private # @since 2.1.0 class Renderer # @api private # @since 2.1.0 PARTIAL_PREFIX = "_" # @api private # @since 2.1.0 PATH_DELIMITER = "/" # @api private # @since 2.1.0 CURRENT_PATH_PREFIX = "." # @api private # @since 2.1.0 attr_reader :config, :prefixes # @api private # @since 2.1.0 def initialize(config) @config = config @prefixes = [CURRENT_PATH_PREFIX] end # @api private # @since 2.1.0 def template(name, format, scope, &block) old_prefixes = @prefixes.dup template_path = lookup(name, format) raise TemplateNotFoundError.new(name, format, config.paths) unless template_path new_prefix = File.dirname(name) @prefixes << new_prefix unless @prefixes.include?(new_prefix) render(template_path, scope, &block) ensure @prefixes = old_prefixes end # @api private # @since 2.1.0 def partial(name, format, scope, &block) template(name_for_partial(name), format, scope, &block) end private def lookup(name, format) View.cache.fetch_or_store(:lookup, name, format, config, prefixes) { catch :found do config.paths.reduce(nil) do |_, path| prefixes.reduce(nil) do |_, prefix| result = path.lookup(prefix, name, format) throw :found, result if result end end end } end def name_for_partial(name) segments = name.to_s.split(PATH_DELIMITER) segments[-1] = "#{PARTIAL_PREFIX}#{segments[-1]}" segments.join(PATH_DELIMITER) end def render(path, scope, &block) tilt(path).render(scope, {locals: scope._locals}, &block).html_safe end def tilt(path) View.cache.fetch_or_store(:tilt, path, config) { Hanami::View::Tilt[path, config.renderer_engine_mapping, config.renderer_options] } end end end end