diff --git a/lib/pronto.rb b/lib/pronto.rb index 62502f8c..51d7d82e 100644 --- a/lib/pronto.rb +++ b/lib/pronto.rb @@ -49,6 +49,7 @@ require 'pronto/formatter/bitbucket_pull_request_formatter' require 'pronto/formatter/bitbucket_server_pull_request_formatter' require 'pronto/formatter/checkstyle_formatter' +require 'pronto/formatter/html_formatter' require 'pronto/formatter/null_formatter' require 'pronto/formatter/formatter' diff --git a/lib/pronto/assets/logo.png b/lib/pronto/assets/logo.png new file mode 100644 index 00000000..c091ad7f Binary files /dev/null and b/lib/pronto/assets/logo.png differ diff --git a/lib/pronto/assets/output.html.erb b/lib/pronto/assets/output.html.erb new file mode 100644 index 00000000..9f88b4e9 --- /dev/null +++ b/lib/pronto/assets/output.html.erb @@ -0,0 +1,119 @@ + + + + + + + + + + Code Analysis Report + + + + + +
+
+
+
<%= pluralize(files.values.flatten.count, 'offense', no_for_zero: true) %> detected:
+
+
+
    + <% files.each do |path, offenses| %> +
  • + <%= path %> + <%= pluralize(offenses.count, 'offense') %> + + + +
  • + <% end %> +
+
+
+ + <% files.each do |path, offenses| %> +
+ + <%= path %> + + <%= pluralize(offenses.count, 'offense') %> + + +
+ <% offenses.each do |offense| %> +
+
+ + Line #<%= offense.line.new_lineno %> + + <%- message = "#{offense.level}: #{decorated_message(offense.msg)}" %> + + <%= message %> + + + <%= offense.runner.to_s.split('::').last %> + +
+
<%= offense.line.line.content.force_encoding('UTF-8') %>
+
+ <% end %> +
+
+ <% end %> +
+ + + \ No newline at end of file diff --git a/lib/pronto/formatter/formatter.rb b/lib/pronto/formatter/formatter.rb index 310b6065..11f2832c 100644 --- a/lib/pronto/formatter/formatter.rb +++ b/lib/pronto/formatter/formatter.rb @@ -22,6 +22,7 @@ def self.names 'json' => JsonFormatter, 'checkstyle' => CheckstyleFormatter, 'text' => TextFormatter, + 'html' => HtmlFormatter, 'null' => NullFormatter }.freeze end diff --git a/lib/pronto/formatter/html_formatter.rb b/lib/pronto/formatter/html_formatter.rb new file mode 100644 index 00000000..57926efb --- /dev/null +++ b/lib/pronto/formatter/html_formatter.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +require 'cgi' +require 'erb' +require 'ostruct' +require 'base64' + +module Pronto + module Formatter + class HtmlFormatter < Base + TEMPLATE_PATH = + File.expand_path('../assets/output.html.erb', __dir__) + + Color = Struct.new(:red, :green, :blue, :alpha) do + def to_s + "rgba(#{values.join(', ')})" + end + + def fade_out(amount) + dup.tap do |color| + color.alpha -= amount + end + end + end + + attr_reader :files, :summary + + def format(messages, _, _) + render_html(messages) + end + + def render_html(messages) + context = ERBContext.new(messages) + + template = File.read(TEMPLATE_PATH, encoding: Encoding::UTF_8) + + erb = if RUBY_VERSION >= '2.6' + ERB.new(template, trim_mode: '-') + else + ERB.new(template, nil, '-') + end + html = erb.result(context.binding) + + html + end + + # This class provides helper methods used in the ERB template. + class ERBContext + + attr_reader :files + + def initialize(messages) + @files = messages.group_by(&:path) + end + + # Make Kernel#binding public. + def binding + super + end + + def decorated_message(msg) + msg.gsub(/`(.+?)`/) do + "#{Regexp.last_match(1)}" + end.force_encoding('UTF-8') + end + + def pluralize(number, thing, options = {}) + if number.zero? && options[:no_for_zero] + "no #{thing}s" + elsif number == 1 + "1 #{thing}" + else + "#{number} #{thing}s" + end + end + + def escape(string) + CGI.escapeHTML(string) + end + end + end + end +end +