require 'jekyll' require_relative '../error/jekyll_plugin_error_handling' module JekyllSupport # Base class for Jekyll generators. # PluginMetaLogger.instance.config is populated with the contents of `_config.yml` before Jekyll::Generator instances run. class JekyllGenerator < Jekyll::Generator attr_reader :helper, :line_number, :logger, :site # Method prescribed by the Jekyll plugin lifecycle. # Defines @config, @envs, @mode and @site # @return [void] def generate(site) @logger ||= PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config) @error_name = "#{self.class.name}Error" # JekyllSupport::CustomError.factory @error_name @site = site @config = @site.config @envs = site.config['env'] @theme = @site.theme @mode = ENV['JEKYLL_ENV'] || 'development' # set_error_context(self.class) generate_impl rescue StandardError => e e.shorten_backtrace @logger.error { "#{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} by #{self.class.name} - #{e.message}" } binding.pry if @pry_on_standard_error # rubocop:disable Lint/Debugger raise e if @die_on_standard_error <<~END_MSG
#{e.class} on line #{@line_number} of #{e.backtrace[0].split(':').first} by #{self.class.name}: #{e.message}
END_MSG end # Jekyll plugins should override this method, not `generate`, so they can be tested more easily. # The following variables are predefined: # @config, @envs, @helper, @logger, @mode, @paginator, @site and @theme # @return [void] def generate_impl; end def self.register(klass) abort("Error: The #{klass.name} plugin does not define VERSION") \ unless klass.const_defined?(:VERSION) version = klass.const_get(:VERSION) error_name_stub = klass.name.include?('::') ? klass.name.split('::')[1] : klass.name error_ruby_class_name = "#{error_name_stub.camelcase(:upper)}Error" error_css_class_name = error_ruby_class_name.split('::').last.snakecase msg = <<~END_MSG Loaded generator plugin #{klass.name} v#{version}. It has: Error class: #{@error_name} CSS class for error messages: #{error_css_class_name} END_MSG PluginMetaLogger.instance.info { msg } end def set_error_context(klass) return unless Object.const_defined? @error_name error_class = Object.const_get @error_name error_class.class_variable_set(:@@argument_string, @argument_string) error_class.class_variable_set(:@@line_number, @line_number) error_class.class_variable_set(:@@path, @page['path']) error_class.class_variable_set(:@@tag_name, klass.name) end end end