diff --git a/lib/jekyll/kroki.rb b/lib/jekyll/kroki.rb index ddc2923..76f7398 100644 --- a/lib/jekyll/kroki.rb +++ b/lib/jekyll/kroki.rb @@ -11,167 +11,165 @@ require "zlib" module Jekyll - # Converts diagram descriptions into images using Kroki - class Kroki - KROKI_DEFAULT_URL = "https://kroki.io" - SUPPORTED_LANGUAGES = %w[actdiag blockdiag bpmn bytefield c4plantuml d2 dbml diagramsnet ditaa erd excalidraw - graphviz mermaid nomnoml nwdiag packetdiag pikchr plantuml rackdiag seqdiag structurizr - svgbob symbolator tikz umlet vega vegalite wavedrom wireviz].freeze - HTTP_MAX_RETRIES = 3 - - class << self - # Renders and embeds all diagram descriptions in a Jekyll site using Kroki. - # - # @param [Jekyll::Site] The Jekyll site to embed diagrams in - def embed_site(site) - # Get the URL of the Kroki instance - kroki_url = kroki_url(site.config) - connection = setup_connection(kroki_url) - - rendered_diag = 0 - (site.pages + site.documents).each do |doc| - next unless embeddable?(doc) - - # Render all supported diagram descriptions in the document - rendered_diag += embed_doc(connection, doc) - end - - unless rendered_diag.zero? - puts "[jekyll-kroki] Rendered #{rendered_diag} diagrams using Kroki instance at '#{kroki_url}'" - end - rescue StandardError => e - exit(e) - end - - # Renders all supported diagram descriptions in a document and embeds them as inline SVGs in the HTML source. - # - # @param [Faraday::Connection] The Faraday connection to use - # @param [Nokogiri::HTML4::Document] The parsed HTML document - # @param [Integer] The number of rendered diagrams - def embed_doc(connection, doc) - # Parse the HTML document - parsed_doc = Nokogiri::HTML(doc.output) - html_tags = %w[code div].freeze - - rendered_diag = 0 +  # Converts diagram descriptions into images using Kroki +  class Kroki +    KROKI_DEFAULT_URL = "https://kroki.io" +    SUPPORTED_LANGUAGES = %w[actdiag blockdiag bpmn bytefield c4plantuml d2 dbml diagramsnet ditaa erd excalidraw +                             graphviz mermaid nomnoml nwdiag packetdiag pikchr plantuml rackdiag seqdiag structurizr +                             svgbob symbolator tikz umlet vega vegalite wavedrom wireviz].freeze +    EXPECTED_HTML_TAGS = %w[code div].freeze +    HTTP_MAX_RETRIES = 3 + +    class << self +      # Renders and embeds all diagram descriptions in a Jekyll site using Kroki. +      # +      # @param [Jekyll::Site] The Jekyll site to embed diagrams in +      def embed_site(site) +        # Get the URL of the Kroki instance +        kroki_url = kroki_url(site.config) +        connection = setup_connection(kroki_url) + +        rendered_diag = 0 +        (site.pages + site.documents).each do |doc| +          next unless embeddable?(doc) + +          # Render all supported diagram descriptions in the document +          rendered_diag += embed_doc(connection, doc) +        end + +        unless rendered_diag.zero? +          puts "[jekyll-kroki] Rendered #{rendered_diag} diagrams using Kroki instance at '#{kroki_url}'" +        end +      rescue StandardError => e +        exit(e) +      end + +      # Renders all supported diagram descriptions in a document and embeds them as inline SVGs in the HTML source. +      # +      # @param [Faraday::Connection] The Faraday connection to use +      # @param [Nokogiri::HTML4::Document] The parsed HTML document +      # @param [Integer] The number of rendered diagrams +      def embed_doc(connection, doc) +        # Parse the HTML document +        parsed_doc = Nokogiri::HTML(doc.output) + +        rendered_diag = 0         SUPPORTED_LANGUAGES.each do |language| -          html_tags.each do |tag| +          EXPECTED_HTML_TAGS.each do |tag|             parsed_doc.css("#{tag}[class~='language-#{language}']").each do |diagram_desc|               # Replace the diagram description with the SVG representation rendered by Kroki               diagram_desc.replace(render_diagram(connection, diagram_desc, language))               rendered_diag += 1             end           end - end - - end - - # Convert the document back to HTML - doc.output = parsed_doc.to_html - rendered_diag - end - - # Renders a single diagram description using Kroki. - # - # @param [Faraday::Connection] The Faraday connection to use - # @param [String] The diagram description - # @param [String] The language of the diagram description - # @return [String] The rendered diagram in SVG format - def render_diagram(connection, diagram_desc, language) - begin - response = connection.get("#{language}/svg/#{encode_diagram(diagram_desc.text)}") - rescue Faraday::Error => e - raise e.message - end - expected_content_type = "image/svg+xml" - returned_content_type = response.headers[:content_type] - if returned_content_type != expected_content_type - raise "Kroki returned an incorrect content type: " \ - "expected '#{expected_content_type}', received '#{returned_content_type}'" - - end - sanitise_diagram(response.body) - end - - # Sanitises a rendered diagram. Only