require "pact/consumer_contract" require "pact/reification" require "redcarpet" require "pact/doc/markdown/consumer_contract_renderer" require "pact_broker/api/pact_broker_urls" require "pact_broker/logging" require "rack" module PactBroker module Api module Renderers class HtmlPactRenderer class NotAPactError < StandardError; end include PactBroker::Logging def self.call pact, options = {} new(pact, options).call end def initialize pact, options = {} @json_content = pact.json_content @pact = pact @options = options end def call " #{head} #{breadcrumbs}#{pact_metadata}#{html} " end private def head "#{title} " end def breadcrumbs " " end def pact_metadata "
" end def badge_list_item "
  • " end def badge_markdown_item "" end def badge_markdown warning = if badges_protected? "If the broker is protected by authentication, set `enable_public_badge_access` to true in the configuration to enable badges to be embedded in a markdown file.\n" else "" end "#{warning}[![#{@pact.consumer.name}/#{@pact.provider.name} Pact Status](#{badge_url})](#{badge_target_url})" end def badges_protected? !PactBroker.configuration.enable_public_badge_access end def base_url @options[:base_url] || "" end def title "Pact between #{consumer_name} and #{provider_name}" end def consumer_version_number h(@pact.consumer_version_number) end def consumer_name h(@pact.consumer.name) end def provider_name h(@pact.provider.name) end def published_date @pact.created_at.to_time.localtime.to_datetime.strftime("%a %d %b %Y, %l:%M%P %:z") end def published_date_in_words PactBroker::DateHelper.distance_of_time_in_words(@pact.created_at.to_time, DateTime.now) + " ago" end def json_url PactBroker::Api::PactBrokerUrls.hal_browser_url pact_url, base_url end def pact_url PactBroker::Api::PactBrokerUrls.pact_url base_url, @pact end def matrix_url PactBroker::Api::PactBrokerUrls.matrix_for_pact_url(@pact, base_url) end def latest_pact_url PactBroker::Api::PactBrokerUrls.latest_pact_url base_url, @pact end def badge_target_url base_url end def badge_url @options[:badge_url] end def tags if @pact.consumer_version_tag_names.any? tag_names = @pact.consumer_version_tag_names.collect{ |t| h(t) }.join(", ") " (#{tag_names})" else "" end end def markdown Pact::Doc::Markdown::ConsumerContractRenderer.call consumer_contract rescue StandardError heading = "### A contract between #{@pact.consumer.name} and #{@pact.provider.name}" warning = "_Note: this contract could not be parsed to a v1 or v2 Pact, showing raw content instead._" pretty_json = JSON.pretty_generate(@pact.content_hash) "#{heading}\n#{warning}\n```json\n#{pretty_json}\n```\n" end def html Redcarpet::Markdown.new(Redcarpet::Render::HTML, :fenced_code_blocks => true, :lax_spacing => true).render(markdown) end def consumer_contract Pact::ConsumerContract.from_json(@json_content) rescue => e logger.info "Could not parse the following content to a Pact due to #{e.class} #{e.message}, showing raw content instead: #{@json_content}" raise NotAPactError end def h string Rack::Utils.escape_html(string) end end end end end