Class: Jekyll::Kroki
- Inherits:
-
Object
- Object
- Jekyll::Kroki
- Defined in:
- lib/jekyll/kroki.rb,
lib/jekyll/kroki/config.rb,
lib/jekyll/kroki/version.rb
Overview
Converts diagram descriptions into images using Kroki.
Defined Under Namespace
Classes: Config
Constant Summary collapse
- 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
- DIAGRAM_SELECTOR =
SUPPORTED_LANGUAGES.flat_map do |language| EXPECTED_HTML_TAGS.map { |tag| "#{tag}[class~='language-#{language}']" } end.join(", ").freeze
- HTTP_RETRY_INTERVAL_BACKOFF_FACTOR =
2- HTTP_RETRY_INTERVAL_RANDOMNESS =
0.5- HTTP_RETRY_INTERVAL =
0.1- VERSION =
"1.0.0"
Class Method Summary collapse
-
.embed_docs_in_site(site, connection, max_concurrent_docs) ⇒ Integer
Renders the diagram descriptions in all Jekyll pages and documents in the given Jekyll site.
-
.embed_single_doc(connection, doc) ⇒ Integer
Renders the supported diagram descriptions in a single document sequentially and embeds them as inline SVGs in the HTML source.
-
.embed_site(site) ⇒ Object
Renders and embeds all diagram descriptions in the given Jekyll site using Kroki.
-
.embeddable?(doc) ⇒ Boolean
Determines whether a document may contain embeddable diagram descriptions; it is in HTML format and is either a Jekyll::Page or writeable Jekyll::Document.
-
.encode_diagram(diagram_desc) ⇒ String
Encodes the diagram into Kroki format using deflate + base64.
-
.render_diagram(connection, diagram_text, language) ⇒ String
Renders a single diagram description using Kroki.
-
.sanitise_diagram(diagram_svg) ⇒ String
Sanitises a rendered diagram.
-
.setup_connection(kroki_url, retries, timeout) ⇒ Faraday::Connection
Sets up a new Faraday connection.
-
.validate_content_type(response) ⇒ Object
Validates that the Kroki response has the expected SVG content type.
Class Method Details
.embed_docs_in_site(site, connection, max_concurrent_docs) ⇒ Integer
Renders the diagram descriptions in all Jekyll pages and documents in the given Jekyll site. Pages / documents are rendered concurrently up to the limit defined by max_concurrent_docs.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/jekyll/kroki.rb', line 58 def (site, connection, max_concurrent_docs) semaphore = Async::Semaphore.new(max_concurrent_docs) Async do (site.pages + site.documents).filter_map do |doc| next unless (doc) semaphore.async do (connection, doc) rescue StandardError => e Jekyll.logger.error "[jekyll-kroki] Failed to render diagram in '#{doc.relative_path}': #{e.}" 0 end end.sum(&:wait) end.wait end |
.embed_single_doc(connection, doc) ⇒ Integer
Renders the supported diagram descriptions in a single document sequentially and embeds them as inline SVGs in the HTML source. Returns without modifying the document if no supported diagram descriptions are found.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/jekyll/kroki.rb', line 81 def (connection, doc) parsed_doc = Nokogiri::HTML(doc.output) nodes = parsed_doc.css(DIAGRAM_SELECTOR) return 0 if nodes.empty? nodes.each do |node| # Extract the diagram language from the class list. language = node["class"].split.grep(/\Alanguage-/).first.delete_prefix("language-") node.replace(render_diagram(connection, node.text, language)) end # Convert the document back to HTML. doc.output = parsed_doc.to_html nodes.size end |
.embed_site(site) ⇒ Object
Renders and embeds all diagram descriptions in the given Jekyll site using Kroki.
39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/jekyll/kroki.rb', line 39 def (site) config = Config.new(site.config) connection = setup_connection(config.kroki_url, config.http_retries, config.http_timeout) rendered_diag = (site, connection, config.max_concurrent_docs) return unless rendered_diag.positive? Jekyll.logger.info( "[jekyll-kroki] Rendered #{rendered_diag} diagrams using Kroki instance at '#{config.kroki_url}'" ) end |
.embeddable?(doc) ⇒ Boolean
Determines whether a document may contain embeddable diagram descriptions; it is in HTML format and is either a Jekyll::Page or writeable Jekyll::Document.
172 173 174 |
# File 'lib/jekyll/kroki.rb', line 172 def (doc) doc.output_ext == ".html" && (doc.is_a?(Jekyll::Page) || doc.write?) end |
.encode_diagram(diagram_desc) ⇒ String
Encodes the diagram into Kroki format using deflate + base64. See https://docs.kroki.io/kroki/setup/encode-diagram/.
144 145 146 |
# File 'lib/jekyll/kroki.rb', line 144 def encode_diagram(diagram_desc) Base64.urlsafe_encode64(Zlib.deflate(diagram_desc, Zlib::BEST_COMPRESSION)) end |
.render_diagram(connection, diagram_text, language) ⇒ String
Renders a single diagram description using Kroki. The rendered diagram is cached to avoid redundant HTTP requests across documents, using the diagram language and the SHA1 of the diagram description as the key.
104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/jekyll/kroki.rb', line 104 def render_diagram(connection, diagram_text, language) cache_key = "#{language}:#{Digest::SHA1.hexdigest(diagram_text)}" @diagram_cache.compute_if_absent(cache_key) do response = connection.get("#{language}/svg/#{encode_diagram(diagram_text)}") validate_content_type(response) sanitise_diagram(response.body) rescue Faraday::BadRequestError => e = e.response_body.to_s.strip raise e, (.empty? ? e. : ) end end |
.sanitise_diagram(diagram_svg) ⇒ String
Sanitises a rendered diagram. Only