This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
require 'facets/string/camelcase'
|
||||
require 'facets/string/snakecase'
|
||||
|
||||
module JekyllSupport
|
||||
# Use like this:
|
||||
# CustomError.new(:MyError, 'blah', 'asdf')
|
||||
class CustomError < StandardError
|
||||
def self.factory(error_class_name)
|
||||
return if Object.const_defined? "::#{error_class_name}"
|
||||
|
||||
Object.const_set error_class_name, Class.new(CustomError)
|
||||
end
|
||||
|
||||
def error_name
|
||||
self.class.name.split('::').last
|
||||
end
|
||||
|
||||
def calling_file
|
||||
file_fq, _line_number, _extra = backtrace[0]&.split(':')
|
||||
file_fq
|
||||
end
|
||||
|
||||
# @return HTML <div> tag with class set to the snake_case version of the error class name.
|
||||
def html_message
|
||||
shorten_backtrace
|
||||
path, line_number, _caller = backtrace[1]&.split(':')
|
||||
<<~END_MSG
|
||||
<div class='#{error_name.snakecase}'>
|
||||
#{self.class} raised in #{calling_file} while processing line #{line_number} (after front matter) of #{path}
|
||||
#{message}
|
||||
</div>
|
||||
END_MSG
|
||||
end
|
||||
|
||||
def logger_message
|
||||
shorten_backtrace
|
||||
kaller = caller(1..1).first
|
||||
path, line_number, _caller = backtrace[1]&.split(':')
|
||||
<<~END_MSG
|
||||
#{error_name} raised in #{kaller} while processing line #{line_number} (after front matter) of #{path}
|
||||
#{message}
|
||||
END_MSG
|
||||
end
|
||||
|
||||
def shorten_backtrace(backtrace_element_count = 3)
|
||||
b = backtrace[0..backtrace_element_count - 1].map do |x|
|
||||
x.gsub(Dir.pwd + '/', './')
|
||||
end
|
||||
set_backtrace b
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,48 @@
|
||||
module JekyllSupportError
|
||||
attr_reader :logger, :page
|
||||
|
||||
# If a Jekyll plugin needs to crash exit, and stop Jekyll, call this method.
|
||||
# It does not generate a stack trace.
|
||||
# This method does not return because the process is abruptly terminated.
|
||||
#
|
||||
# @param error StandardError or a subclass of StandardError is required
|
||||
#
|
||||
# Do not raise the error before calling this method, just create it via 'new', like this:
|
||||
# exit_without_stack_trace StandardError.new('This is my error message')
|
||||
#
|
||||
# If you want to call this method from a handler method, the default index for the backtrace array must be specified.
|
||||
# The default backtrace index is 1, which means the calling method.
|
||||
# To specify the calling method's caller, pass in 2, like this:
|
||||
# exit_without_stack_trace StandardError.new('This is my error message'), 2
|
||||
def exit_without_stack_trace(error, caller_index = 1)
|
||||
raise error
|
||||
rescue StandardError => e
|
||||
file, line_number, caller = e.backtrace[caller_index].split(':')
|
||||
caller = caller.tr('`', "'")
|
||||
warn "#{error.message} #{caller} on line #{line_number} (after front matter) of #{file}".red
|
||||
# Process.kill('HUP', Process.pid) # generates huge stack trace
|
||||
exec "echo ''"
|
||||
end
|
||||
|
||||
def format_error_message(message)
|
||||
page = " of #{@page['path']}" if @page
|
||||
remove_ansi_color "on line #{line_number} (after front matter)#{page}.\n#{message}"
|
||||
end
|
||||
|
||||
def remove_ansi_color(string)
|
||||
string.gsub(/\e\[([;\d]+)?m/, '')
|
||||
end
|
||||
|
||||
def maybe_reraise_error(error, throw_error: true)
|
||||
fmsg = format_error_message "#{error.class}: #{error.message.strip}"
|
||||
@logger.error { fmsg }
|
||||
return "<span class='jekyll_plugin_support_error'>#{fmsg}</span>" unless throw_error
|
||||
|
||||
error.set_backtrace error.backtrace[0..9]
|
||||
raise error
|
||||
end
|
||||
|
||||
def warn_short_trace(error)
|
||||
JekyllSupport.warn_short_trace(@logger, error)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user