asciidoctor-kroki-0.10.0/0000755000004100000410000000000014620142421015234 5ustar www-datawww-dataasciidoctor-kroki-0.10.0/.asciidoctor/0000755000004100000410000000000014620142421017615 5ustar www-datawww-dataasciidoctor-kroki-0.10.0/.asciidoctor/kroki/0000755000004100000410000000000014620142421020734 5ustar www-datawww-dataasciidoctor-kroki-0.10.0/.asciidoctor/kroki/.gitkeep0000644000004100000410000000000014620142421022353 0ustar www-datawww-dataasciidoctor-kroki-0.10.0/Gemfile.lock0000644000004100000410000000235314620142421017461 0ustar www-datawww-dataPATH remote: . specs: asciidoctor-kroki (0.10.0) asciidoctor (~> 2.0) GEM remote: https://rubygems.org/ specs: asciidoctor (2.0.22) ast (2.4.2) diff-lcs (1.4.4) parallel (1.22.1) parser (3.1.2.0) ast (~> 2.4.1) rainbow (3.1.1) rake (13.0.6) regexp_parser (2.5.0) rexml (3.2.5) rspec (3.10.0) rspec-core (~> 3.10.0) rspec-expectations (~> 3.10.0) rspec-mocks (~> 3.10.0) rspec-core (3.10.1) rspec-support (~> 3.10.0) rspec-expectations (3.10.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) rspec-mocks (3.10.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) rspec-support (3.10.2) rubocop (1.30.0) parallel (~> 1.10) parser (>= 3.1.0.0) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) rubocop-ast (>= 1.18.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) rubocop-ast (1.18.0) parser (>= 3.1.1.0) ruby-progressbar (1.11.0) unicode-display_width (2.1.0) PLATFORMS ruby DEPENDENCIES asciidoctor-kroki! rake (~> 13.0.6) rspec (~> 3.10.0) rubocop (~> 1.30) BUNDLED WITH 2.3.15 asciidoctor-kroki-0.10.0/.gitignore0000644000004100000410000000003014620142421017215 0ustar www-datawww-datapkg/ .asciidoctor/kroki asciidoctor-kroki-0.10.0/tasks/0000755000004100000410000000000014620142421016361 5ustar www-datawww-dataasciidoctor-kroki-0.10.0/tasks/rspec.rake0000644000004100000410000000023014620142421020334 0ustar www-datawww-data# frozen_string_literal: true begin require 'rspec/core/rake_task' RSpec::Core::RakeTask.new :spec rescue LoadError warn $ERROR_INFO.message end asciidoctor-kroki-0.10.0/tasks/lint.rake0000644000004100000410000000013014620142421020165 0ustar www-datawww-data# frozen_string_literal: true require 'rubocop/rake_task' RuboCop::RakeTask.new :lint asciidoctor-kroki-0.10.0/tasks/bundler.rake0000644000004100000410000000016314620142421020660 0ustar www-datawww-data# frozen_string_literal: true begin require 'bundler/gem_tasks' rescue LoadError warn $ERROR_INFO.message end asciidoctor-kroki-0.10.0/lib/0000755000004100000410000000000014620142421016002 5ustar www-datawww-dataasciidoctor-kroki-0.10.0/lib/asciidoctor/0000755000004100000410000000000014620142421020305 5ustar www-datawww-dataasciidoctor-kroki-0.10.0/lib/asciidoctor/extensions/0000755000004100000410000000000014620142421022504 5ustar www-datawww-dataasciidoctor-kroki-0.10.0/lib/asciidoctor/extensions/asciidoctor_kroki/0000755000004100000410000000000014620142421026206 5ustar www-datawww-dataasciidoctor-kroki-0.10.0/lib/asciidoctor/extensions/asciidoctor_kroki/version.rb0000644000004100000410000000015514620142421030221 0ustar www-datawww-data# frozen_string_literal: true module Asciidoctor module AsciidoctorKroki VERSION = '0.10.0' end end asciidoctor-kroki-0.10.0/lib/asciidoctor/extensions/asciidoctor_kroki/extension.rb0000644000004100000410000003336414620142421030560 0ustar www-datawww-data# frozen_string_literal: true require 'cgi' require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal' # Asciidoctor extensions # module AsciidoctorExtensions include Asciidoctor # A block extension that converts a diagram into an image. # class KrokiBlockProcessor < Extensions::BlockProcessor use_dsl on_context :listing, :literal name_positional_attributes 'target', 'format' # @param name [String] name of the block macro (optional) # @param config [Hash] a config hash (optional) # - :logger a logger used to log warning and errors (optional) # def initialize(name = nil, config = {}) @logger = (config || {}).delete(:logger) { ::Asciidoctor::LoggerManager.logger } super(name, config) end def process(parent, reader, attrs) diagram_type = @name diagram_text = reader.string KrokiProcessor.process(self, parent, attrs, diagram_type, diagram_text, @logger) end protected attr_reader :logger end # A block macro extension that converts a diagram into an image. # class KrokiBlockMacroProcessor < Asciidoctor::Extensions::BlockMacroProcessor include Asciidoctor::Logging use_dsl name_positional_attributes 'format' # @param name [String] name of the block macro (optional) # @param config [Hash] a config hash (optional) # - :logger a logger used to log warning and errors (optional) # def initialize(name = nil, config = {}) @logger = (config || {}).delete(:logger) { ::Asciidoctor::LoggerManager.logger } super(name, config) end def process(parent, target, attrs) diagram_type = @name target = parent.apply_subs(target, [:attributes]) unless read_allowed?(target) link = create_inline(parent, :anchor, target, type: :link, target: target) return create_block(parent, :paragraph, link.convert, {}, content_model: :raw) end unless (path = resolve_target_path(target)) logger.error message_with_context "#{diagram_type} block macro not found: #{target}.", source_location: parent.document.reader.cursor_at_mark return create_block(parent, 'paragraph', unresolved_block_macro_message(diagram_type, target), {}) end begin diagram_text = read(path) rescue => e # rubocop:disable Style/RescueStandardError logger.error message_with_context "Failed to read #{diagram_type} file: #{path}. #{e}.", source_location: parent.document.reader.cursor_at_mark return create_block(parent, 'paragraph', unresolved_block_macro_message(diagram_type, path), {}) end KrokiProcessor.process(self, parent, attrs, diagram_type, diagram_text, @logger) end protected attr_reader :logger def resolve_target_path(target) target end def read_allowed?(_target) true end def read(target) if target.start_with?('http://') || target.start_with?('https://') require 'open-uri' ::OpenURI.open_uri(target, &:read) else File.read(target, mode: 'rb:utf-8:utf-8') end end def unresolved_block_macro_message(name, target) "Unresolved block macro - #{name}::#{target}[]" end end # Kroki API # module Kroki SUPPORTED_DIAGRAM_NAMES = %w[ actdiag blockdiag bpmn bytefield c4plantuml d2 dbml ditaa erd excalidraw graphviz mermaid nomnoml nwdiag packetdiag pikchr plantuml rackdiag seqdiag svgbob symbolator umlet vega vegalite wavedrom structurizr diagramsnet wireviz ].freeze end # Internal processor # class KrokiProcessor include Asciidoctor::Logging TEXT_FORMATS = %w[txt atxt utxt].freeze BUILTIN_ATTRIBUTES = %w[target width height format fallback link float align role caption title cloaked-context subs].freeze class << self # rubocop:disable Metrics/AbcSize def process(processor, parent, attrs, diagram_type, diagram_text, logger) doc = parent.document diagram_text = prepend_plantuml_config(diagram_text, diagram_type, doc, logger) # If "subs" attribute is specified, substitute accordingly. # Be careful not to specify "specialcharacters" or your diagram code won't be valid anymore! if (subs = attrs['subs']) diagram_text = parent.apply_subs(diagram_text, parent.resolve_subs(subs)) end attrs.delete('opts') format = get_format(doc, attrs, diagram_type) attrs['role'] = get_role(format, attrs['role']) attrs['format'] = format opts = attrs.filter { |key, _| key.is_a?(String) && BUILTIN_ATTRIBUTES.none? { |k| key == k } && !key.end_with?('-option') } kroki_diagram = KrokiDiagram.new(diagram_type, format, diagram_text, attrs['target'], opts) kroki_client = KrokiClient.new({ server_url: server_url(doc), http_method: http_method(doc), max_uri_length: max_uri_length(doc), source_location: doc.reader.cursor_at_mark, http_client: KrokiHttpClient }, logger) alt = get_alt(attrs) title = attrs.delete('title') caption = attrs.delete('caption') if TEXT_FORMATS.include?(format) text_content = kroki_client.text_content(kroki_diagram) block = processor.create_block(parent, 'literal', text_content, attrs) else attrs['alt'] = alt attrs['target'] = create_image_src(doc, kroki_diagram, kroki_client) block = processor.create_image_block(parent, attrs) end block.title = title if title block.assign_caption(caption, 'figure') block end # rubocop:enable Metrics/AbcSize private def prepend_plantuml_config(diagram_text, diagram_type, doc, logger) if diagram_type == :plantuml && doc.safe < ::Asciidoctor::SafeMode::SECURE && doc.attr?('kroki-plantuml-include') # REMIND: this behaves different than the JS version # Once we have a preprocessor for Ruby, the value should be added in the diagram source as "!include #{plantuml_include}" plantuml_include_path = doc.normalize_system_path(doc.attr('kroki-plantuml-include')) if ::File.readable? plantuml_include_path config = File.read(plantuml_include_path) diagram_text = "#{config}\n#{diagram_text}" else logger.warn message_with_context "Unable to read plantuml-include. File not found or not readable: #{plantuml_include_path}.", source_location: doc.reader.cursor_at_mark end end diagram_text end def get_alt(attrs) if (title = attrs['title']) title elsif (target = attrs['target']) target else 'Diagram' end end def get_role(format, role) if role if format "#{role} kroki-format-#{format} kroki" else "#{role} kroki" end else 'kroki' end end def get_format(doc, attrs, diagram_type) format = attrs['format'] || doc.attr('kroki-default-format') || 'svg' if format == 'png' # redirect PNG format to SVG if the diagram library only supports SVG as output format. # this is useful when the default format has been set to PNG # Currently, nomnoml, svgbob, wavedrom only support SVG as output format. svg_only_diagram_types = %i[nomnoml svgbob wavedrom] format = 'svg' if svg_only_diagram_types.include?(diagram_type) end format end def create_image_src(doc, kroki_diagram, kroki_client) if doc.attr('kroki-fetch-diagram') && doc.safe < ::Asciidoctor::SafeMode::SECURE kroki_diagram.save(output_dir_path(doc), kroki_client) else kroki_diagram.get_diagram_uri(server_url(doc)) end end def server_url(doc) doc.attr('kroki-server-url', 'https://kroki.io') end def http_method(doc) doc.attr('kroki-http-method', 'adaptive').downcase end def max_uri_length(doc) doc.attr('kroki-max-uri-length', '4000').to_i end def output_dir_path(doc) images_dir = doc.attr('imagesdir', '') if (images_output_dir = doc.attr('imagesoutdir')) images_output_dir # the nested document logic will become obsolete once https://github.com/asciidoctor/asciidoctor/commit/7edc9da023522be67b17e2a085d72e056703a438 is released elsif (out_dir = doc.attr('outdir') || (doc.nested? ? doc.parent_document : doc).options[:to_dir]) File.join(out_dir, images_dir) else File.join(doc.base_dir, images_dir) end end end end # Kroki diagram # class KrokiDiagram require 'fileutils' require 'zlib' require 'digest' attr_reader :type, :text, :format, :target, :opts def initialize(type, format, text, target = nil, opts = {}) @text = text @type = type @format = format @target = target @opts = opts end def get_diagram_uri(server_url) query_params = opts.map { |k, v| "#{k}=#{_url_encode(v.to_s)}" }.join('&') unless opts.empty? _join_uri_segments(server_url, @type, @format, encode) + (query_params ? "?#{query_params}" : '') end def encode ([Zlib::Deflate.deflate(@text, 9)].pack 'm0').tr '+/', '-_' end def save(output_dir_path, kroki_client) diagram_url = get_diagram_uri(kroki_client.server_url) diagram_name = "#{@target || 'diag'}-#{Digest::SHA256.hexdigest diagram_url}.#{@format}" file_path = File.join(output_dir_path, diagram_name) encoding = case @format when 'txt', 'atxt', 'utxt', 'svg' 'utf8' else 'binary' end # file is either (already) on the file system or we should read it from Kroki unless File.exist?(file_path) contents = kroki_client.get_image(self, encoding) FileUtils.mkdir_p(output_dir_path) File.write(file_path, contents, mode: 'wb') end diagram_name end private def _url_encode(text) CGI.escape(text).gsub(/\+/, '%20') end def _join_uri_segments(base, *uris) segments = [] # remove trailing slashes segments.push(base.gsub(%r{/+$}, '')) segments.concat(uris.map do |uri| # remove leading and trailing slashes uri.to_s .gsub(%r{^/+}, '') .gsub(%r{/+$}, '') end) segments.join('/') end end # Kroki client # class KrokiClient include Asciidoctor::Logging attr_reader :server_url, :method, :max_uri_length SUPPORTED_HTTP_METHODS = %w[get post adaptive].freeze def initialize(opts, logger = ::Asciidoctor::LoggerManager.logger) @server_url = opts[:server_url] @max_uri_length = opts.fetch(:max_uri_length, 4000) @http_client = opts[:http_client] method = opts.fetch(:http_method, 'adaptive').downcase if SUPPORTED_HTTP_METHODS.include?(method) @method = method else logger.warn message_with_context "Invalid value '#{method}' for kroki-http-method attribute. The value must be either: " \ "'get', 'post' or 'adaptive'. Proceeding using: 'adaptive'.", source_location: opts[:source_location] @method = 'adaptive' end end def text_content(kroki_diagram) get_image(kroki_diagram, 'utf-8') end def get_image(kroki_diagram, encoding) type = kroki_diagram.type format = kroki_diagram.format text = kroki_diagram.text opts = kroki_diagram.opts if @method == 'adaptive' || @method == 'get' uri = kroki_diagram.get_diagram_uri(server_url) if uri.length > @max_uri_length # The request URI is longer than the max URI length. if @method == 'get' # The request might be rejected by the server with a 414 Request-URI Too Large. # Consider using the attribute kroki-http-method with the value 'adaptive'. @http_client.get(uri, opts, encoding) else @http_client.post("#{@server_url}/#{type}/#{format}", text, opts, encoding) end else @http_client.get(uri, opts, encoding) end else @http_client.post("#{@server_url}/#{type}/#{format}", text, opts, encoding) end end end # Kroki HTTP client # class KrokiHttpClient require 'net/http' require 'uri' require 'json' class << self REFERER = "asciidoctor/kroki.rb/#{Asciidoctor::AsciidoctorKroki::VERSION}" def get(uri, opts, _) uri = URI(uri) headers = opts.transform_keys { |key| "Kroki-Diagram-Options-#{key}" } .merge({ 'referer' => REFERER }) request = ::Net::HTTP::Get.new(uri, headers) ::Net::HTTP.start( uri.hostname, uri.port, use_ssl: (uri.scheme == 'https') ) do |http| http.request(request).body end end def post(uri, data, opts, _) headers = opts.transform_keys { |key| "Kroki-Diagram-Options-#{key}" } .merge({ 'Content-Type' => 'text/plain', 'referer' => REFERER }) res = ::Net::HTTP.post( URI(uri), data, headers ) res.body end end end end asciidoctor-kroki-0.10.0/lib/asciidoctor/extensions/asciidoctor_kroki.rb0000644000004100000410000000066614620142421026543 0ustar www-datawww-data# frozen_string_literal: true require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal' require_relative 'asciidoctor_kroki/version' require_relative 'asciidoctor_kroki/extension' Asciidoctor::Extensions.register do ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES.each do |name| block_macro ::AsciidoctorExtensions::KrokiBlockMacroProcessor, name block ::AsciidoctorExtensions::KrokiBlockProcessor, name end end asciidoctor-kroki-0.10.0/lib/asciidoctor-kroki.rb0000644000004100000410000000023614620142421021750 0ustar www-datawww-data# rubocop:disable Naming/FileName # rubocop:enable Naming/FileName # frozen_string_literal: true require_relative 'asciidoctor/extensions/asciidoctor_kroki' asciidoctor-kroki-0.10.0/spec/0000755000004100000410000000000014620142421016166 5ustar www-datawww-dataasciidoctor-kroki-0.10.0/spec/asciidoctor_kroki_diagram_spec.rb0000644000004100000410000001237114620142421024717 0ustar www-datawww-data# frozen_string_literal: true require 'rspec_helper' require 'asciidoctor' require_relative '../lib/asciidoctor/extensions/asciidoctor_kroki' describe ::AsciidoctorExtensions::KrokiDiagram do it 'should compute a diagram URI' do kroki_diagram = ::AsciidoctorExtensions::KrokiDiagram.new('vegalite', 'png', '{}') diagram_uri = kroki_diagram.get_diagram_uri('http://localhost:8000') expect(diagram_uri).to eq('http://localhost:8000/vegalite/png/eNqrrgUAAXUA-Q==') end it 'should compute a diagram URI with a trailing slashes' do kroki_diagram = ::AsciidoctorExtensions::KrokiDiagram.new('vegalite', 'png', '{}') diagram_uri = kroki_diagram.get_diagram_uri('https://my.domain.org/kroki/') expect(diagram_uri).to eq('https://my.domain.org/kroki/vegalite/png/eNqrrgUAAXUA-Q==') end it 'should compute a diagram URI with trailing slashes' do kroki_diagram = ::AsciidoctorExtensions::KrokiDiagram.new('vegalite', 'png', '{}') diagram_uri = kroki_diagram.get_diagram_uri('https://my-server/kroki//') expect(diagram_uri).to eq('https://my-server/kroki/vegalite/png/eNqrrgUAAXUA-Q==') end it 'should compute a diagram URI with query parameters' do text = %q{ .---. /-o-/-- .-/ / /-> ( * \/ '-. \ \ / ' } opts = { 'stroke-width' => 1, 'background' => 'black' } kroki_diagram = ::AsciidoctorExtensions::KrokiDiagram.new('svgbob', 'png', text, nil, opts) diagram_uri = kroki_diagram.get_diagram_uri('http://localhost:8000') expect(diagram_uri).to eq('http://localhost:8000/svgbob/png/eNrjUoAAPV1dXT0uCFtfN19XX1eXCyysrwCEunZAjoaCloJCjD5IWF1XD8gEK49R0IdoUwdTAN3kC7U=?stroke-width=1&background=black') end it 'should encode a diagram text definition' do kroki_diagram = ::AsciidoctorExtensions::KrokiDiagram.new('plantuml', 'txt', ' alice -> bob: hello') diagram_definition_encoded = kroki_diagram.encode expect(diagram_definition_encoded).to eq('eNpTSMzJTE5V0LVTSMpPslLISM3JyQcAQAwGaw==') end it 'should fetch a diagram from Kroki and save it to disk' do kroki_diagram = ::AsciidoctorExtensions::KrokiDiagram.new('plantuml', 'txt', ' alice -> bob: hello') kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'https://kroki.io', http_method: 'get', http_client: kroki_http_client) output_dir_path = "#{__dir__}/../.asciidoctor/kroki" diagram_name = kroki_diagram.save(output_dir_path, kroki_client) diagram_path = File.join(output_dir_path, diagram_name) expect(File.exist?(diagram_path)).to be_truthy, "diagram should be saved at: #{diagram_path}" content = <<-TXT.chomp ,-----. ,---. |alice| |bob| `--+--' `-+-' | hello | |-------------->| ,--+--. ,-+-. |alice| |bob| `-----' `---' TXT expect(File.read(diagram_path).split("\n").map(&:rstrip).join("\n")).to eq(content) end it 'should fetch a diagram from Kroki and save it to disk using the target name' do kroki_diagram = ::AsciidoctorExtensions::KrokiDiagram.new('plantuml', 'txt', ' alice -> bob: hello', 'hello-world') kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'https://kroki.io', http_method: 'get', http_client: kroki_http_client) output_dir_path = "#{__dir__}/../.asciidoctor/kroki" diagram_name = kroki_diagram.save(output_dir_path, kroki_client) diagram_path = File.join(output_dir_path, diagram_name) expect(diagram_name).to start_with('hello-world-'), "diagram name should use the target as a prefix, got: #{diagram_name}" expect(File.exist?(diagram_path)).to be_truthy, "diagram should be saved at: #{diagram_path}" content = <<-TXT.chomp ,-----. ,---. |alice| |bob| `--+--' `-+-' | hello | |-------------->| ,--+--. ,-+-. |alice| |bob| `-----' `---' TXT expect(File.read(diagram_path).split("\n").map(&:rstrip).join("\n")).to eq(content) end it 'should fetch a diagram from Kroki with the same definition only once' do kroki_diagram = ::AsciidoctorExtensions::KrokiDiagram.new('plantuml', 'png', ' guillaume -> dan: hello') kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'https://kroki.io', http_method: 'get', http_client: kroki_http_client) output_dir_path = "#{__dir__}/../.asciidoctor/kroki" # make sure that we are doing only one GET request diagram_contents = File.read("#{__dir__}/fixtures/plantuml-diagram.png", mode: 'rb') expect(kroki_http_client).to receive(:get).once.and_return(diagram_contents) diagram_name = kroki_diagram.save(output_dir_path, kroki_client) diagram_path = File.join(output_dir_path, diagram_name) expect(File.exist?(diagram_path)).to be_truthy, "diagram should be saved at: #{diagram_path}" # calling again... should read the file from disk (and not do a GET request) kroki_diagram.save(output_dir_path, kroki_client) expect(File.size(diagram_path)).to be_eql(diagram_contents.length), 'diagram should be fully saved on disk' end end asciidoctor-kroki-0.10.0/spec/asciidoctor_kroki_client_spec.rb0000644000004100000410000000726014620142421024572 0ustar www-datawww-data# frozen_string_literal: true require 'rspec_helper' require 'asciidoctor' require_relative '../lib/asciidoctor/extensions/asciidoctor_kroki' describe ::AsciidoctorExtensions::KrokiClient do it 'should use adaptive method when http method is invalid' do kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'patch', http_client: kroki_http_client) expect(kroki_client.method).to eq('adaptive') end it 'should use post method when http method is post' do kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'POST', http_client: kroki_http_client) expect(kroki_client.method).to eq('post') end it 'should use get method when http method is get' do kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'get', http_client: kroki_http_client) expect(kroki_client.method).to eq('get') end it 'should use 4000 as the default max URI length' do kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'get', http_client: kroki_http_client) expect(kroki_client.max_uri_length).to eq(4000) end it 'should use a custom value as max URI length' do kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'get', http_client: kroki_http_client, max_uri_length: 8000) expect(kroki_client.max_uri_length).to eq(8000) end it 'should get an image with POST request if the URI length is greater than the value configured' do kroki_http_client = Class.new do class << self def get(uri, _) "GET #{uri}" end def post(uri, data, _, _) "POST #{uri} - #{data}" end end end kroki_diagram = Class.new do attr_reader :type, :text, :format, :opts def initialize(type, format, text, opts = {}) @text = text @type = type @format = format @opts = opts end def get_diagram_uri(_) 'diagram-uri' end end.new('type', 'format', 'text') kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'adaptive', http_client: kroki_http_client, max_uri_length: 10) result = kroki_client.get_image(kroki_diagram, 'utf8') expect(result).to eq('POST http://localhost:8000/type/format - text') end it 'should get an image with GET request if the URI length is lower or equals than the value configured' do kroki_http_client = Class.new do class << self def get(uri, _, _) "GET #{uri}" end def post(uri, data, _, _) "POST #{uri} - #{data}" end end end kroki_diagram = Class.new do attr_reader :type, :text, :format, :opts def initialize(type, format, text, opts = {}) @text = text @type = type @format = format @opts = opts end def get_diagram_uri(_) 'diagram-uri' end end.new('type', 'format', 'text') kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'adaptive', http_client: kroki_http_client, max_uri_length: 11) result = kroki_client.get_image(kroki_diagram, 'utf8') expect(result).to eq('GET diagram-uri') end end asciidoctor-kroki-0.10.0/spec/fixtures/0000755000004100000410000000000014620142421020037 5ustar www-datawww-dataasciidoctor-kroki-0.10.0/spec/fixtures/config.puml0000644000004100000410000000003214620142421022176 0ustar www-datawww-dataskinparam monochrome true asciidoctor-kroki-0.10.0/spec/fixtures/plantuml-diagram.png0000644000004100000410000006650414620142421024016 0ustar www-datawww-dataPNG  IHDR5AD)tEXtcopyleftGenerated by http://plantuml.com09iTXtplantumlxmRN@bl )Uhca{Ѫ4p7oޛ79, u5vFPkœ5}HYl j(AIOZ agY׊+Ԗj$ j-\u<ZO(Ƃ%mw.H_ƹT4_#0;+|Ъ59{ xƽB׍&̛?Xw&hAZ.A}0O3e,ɠ7vCsq[I| {4Vi(8J2\4>iI 7:z*&7K5B,ib!~Ī7Ho|2?5a%\\Stp}K㭻ĥvq+ \%ZKk!IDATx^wXWۇ1111ɛ^^b=EE 6DED vEA TP,T]{>`dݙk9S}TDAg?%B!(P(VZş wA(e8mƟ wA(ek.$Ԡg?%B!L2tP P:d(S E(2)C"ʔ!CJ eʐC2eP!C2d(B鐡L2tP P:d(S E(2)C"ʔ!CJ eʐC2eP!CIúu6o72tPPbE -Z E 55OMll,VjժZjegg<==5>##M9ۼy3N:ӗ(Q"xxxhNW_!x?qo߿]2tPoqBCC4i"~ٳU;v dff ݻ7>>֖M @C)aaacBnܸm`GNJJBB(o&vqC"s,}v5j̚5EكiiiDDD -Z&X@C3fee}Lj4nܘE49TǎwYnݝ;wYr%6לo E(5ȑ#Yb%K paƸ8gϞ0^c*00PJ*|BD 4(~y%''{7C"JC-]Ejر #7ڵkYJKCBTlYg= CJ fC?~ C̮PA kժ&@=umnP!CPmhh(%f(,D0J|o5g/_o E(2ԛ %TL[p+\,"8H+CٓMpA=z({ۡCa<+P1M:"񱴴P02tPo6ΦvڱvvvlΝ;}GKfRJ , d(B阝n߾FX[M,r)gK.c#Fh֬Y=nz˗c6qg?ͮyW:ƃq"7޽;?x`INN4i*!1cWtP1;Cd(B鐡L2tP P:d(S E(2)C"ʔ!CJ eʐC2eP!C2d(B鐡L2tP P:d(S E(2)C"ʔ!CJGن:p?BG03qmd/3qm5jӇ?5Avvvk+6.z8P6DMQaC*6}-A]FA0`B 2P7#555ؠrԀ|ADJD %T*`( 2dBrPA"!CI $ %d(2dBrPA"!CI $ %d(2dBrPA"!CI $ %d(2dBrPA"!CI $ %d(2dBrPA"!CI $ %d(2dBrdd׎#_9(1d⍼P9995j= ~s b?kkk_ *:%d#iG3Եkא@FϡtمB FP@ DAtمB FP P:@9FC 2P␡$ c8d( C!.?[fΝM=z6mڤTl;wm A0t1T-^coo/322J(!4͛7OcBd+_d((,Q\CիWOE6֭[mdffm A0t7{WTz,>qD?Ά0ۼy3W+}K+&&ի7nܾ}Ǐ5g'd((,4i/[:'m۶-g(2dS(7}#Fꫯ A0eQFᅇyyy`fEk-ܹs 4 4OթSGcJ 1`Pŏ?ٳgrݺu)Pݻw/O/^Xy3r-NKK[lYɒ%ڡC մiSau-p!(CP:PXXjժu||g(aY' qCo^M>M,eJ 1`PŋשS/bcc9C͞=QKPP E*<Q\CaԆڵ{뭷J.3PʕP˗s(2#Fq > e˖pbk֬wڵ E*<Q\C2b5?~|jܸ1{[zmڴaK#C3A0k(o1os:v옠w}wԩwy8N2g 1`b(m ݴioh*&d(*S2P:@9FC 2P␡$ c8d( C!J2P:@9FC 2P␡$ c8d(xųg b |Ԍ#!Ci͒%K  0/5o(qPZ~& 1f!Jk?nmm_R"bz\W3NP␡taNR A% !J222*VI@C zKX#!C鈋 0=rxd(9s#&)Pz_A9F 2tAdt=-^kIx1A9FCҝ[ })5 r ;Md !Xġ D#!C ᶃ  ġ#!Cᶃ ġ#!CC7C9FC4 !J&7B9FCo; !Jv@71B24pMEr %MEr UO<~zBBBLLLXXƍ/_>[̈́ `ྗ7XΜ9sL,y˖-XKbb"֘oc9F35ԭ[v-HgذaNNNFBpҥk֬ MRUoo͛lQǎÒ|ktssc .[v={N:u]~7 ! &n/^$''~~~Ǐ?LԩSW\/^-+6l@/ߠ+Ytt4iUVEEEYQ@z u…;wb 1RC$^HBff/|\vСC^^^L[#FݻwQbD¹ %M<J°hgΜiCq>d222`׻:Zx1,"r0"41A`oo?}t(X^3qqq#GD/A[wV?##db uu1+aw Lԍ72[yzz=z4//bc #d a2~Rxeˆ k׮'On@cnܸ1w\;;;IFHAzzzHH#Tua#eOAqq"CZZA͜9i,b,M[n! Ǐ9r.\~0dJL2bĈX ;{͛7bp},ڵk|r ӥK%51BPϞ=Q4aiaa`ܹs˄yu;S{c1mmm#""3C*TXr%P ޽e2Ȗ'N 0`߾}aPƍCy r0 `'߿?>>>33388xK.MOOGfBp}Y0cMӧOl}][,Nj'Oz{{cvء9=\xt.]h"l^p1ّ#GiIHH"9 (ʄ䄇;99I.)=a2PoٲO=Pz=z4m5k ˔)ST)D/L?iҤz %KZի}5p@+++___L;#V;;;azFtt4⮮A8?Bi cW^ɰhС/?н{3˗A-1”06mڴf> o:eN]8'44TH5ׯmbb"&Xْy--`UxaܹslLSre-}R~aEl!ǎBR0%56%XD>Հ׮]ٓ+Vk1<pz=z/322[+9u^GDD4k 5Vo(]~0"QQQB1n8:ܹo͛gnݺ}G7@R0Ǟ={0Ua ;"111`3zŒze0#tuE#L Cz|0j"mBBNc1fa" :ڵ y{ľ}ĉ5 e+8C}͛7?oPpk.++ Վ;bkP(0̙3Aڐ- .]]]6p9r{|0Nx-3 uҥRJjↂ&kFa 4L~ӧ~ڽ{w4FX [5b0/&CZfMz׾}{S _A>|8tuE#L i'>Pk֬ U"k۶m)));v찐PӧOP۷ogqzwZn+cbuCa}SNGGGꊴ9F3j(C>;E+Cm/π6m$Ο?[o7[n*Tnq UV sM???˗/c!j*D֭[f_C~aj(PW>pzC+Ch PH/O7C,oZ1 ZjҥǏ/9C3o7n(L0{lD(aÆ^(O"l'b˖-㏮Hca8C=ydȐ!| b+t0o޼MⴷP0P-p{'Xp!"Jbb K*M{.Y`*U%BdB 4ѣGis0= g(DگWߺu r%0ŧ~\rn]pڵ¢a_ƢZk@1A=\BpڵBӷo?φ m ǎN|0Bk1<à(C'@XXشi#Z}?TRc#, 8yȑ#ǎ{INN={6t`<?<9F(0iҤG!5)))aN=c# %pM__ߡC5j˖-_"!O\\*&iܸqo(cp:mݺ@ 'UTT^m`憞?s6821B(P[v#pwww x""w^ll,qΰ׾}5j1cƬX">>ɓ'|eaxLPbbbV^=e8 YfMddɓ'SSS^6']|9..n޽ հ}޴iөSd5p oLP3 ,َ`j-[@dǎKRyĥK=o޼Zp!;rHPoÇ_; I!!fg7zUBBoT3uT Ymڴ:t(aiӦc;v8tٳgQ4i> bz tg?>zhkk3gmJr %Ν;x 5Vڶm {(qP&Bttt5͛71B2p#gϞmrr eRܽ{]vGVV&K(qPƓ'O дi+Wmr eMU'OYի}B9FC8q*3gԪUkŊ|ޠ#!C`ڵ@9FC"x֭h"AP␡pB}}}#!C\Vk B9FC" իW r Eqȑjժݻo1B2I:to1B2fn݊^||j|;۽{wI~r 5111|ի޽{ϟ!哓Ӯ];777A{(qPZf͚ҥ˖-[ NAw/^7h !Jk222*W|Q j={hF"""Ǝ11Ο?_zbT !JZhQF+WVZi\xx8,v5!bDGGWVɓ|C#!C´i3M4b;v찴tqq Ƽ׿qP4(qP~{ںSNO>Enݺ~͛7lٲ&_@ L<%"@9FCґMs[GGGŘ.555$$RP<[[۞={xo{c8d(?kמ5kŋHͧbx0ףG={Vc8dbѱcG 񘞨b@ֳg r U,֬YSvm*8bcc+TPW9(qPE%71B2TqڵkժUxe~|c8d₁z ܿfٲe|c8dӧׯ_OLL<|pXXXpp9s|8;;;--- 7f̙XȬYP,̙3Xד'O09N<7Ƭr2۷ccc7mڴh"wwwA"Æ suuB<00pݑgϞMJJ:M! saX/U 3f̼y6lpAtŲ`G^bz!.ЁSt0y+VٳMiiiKJzz:j+X F ;G!##I%ŋvڡ(:`:B} e8PEGG2PnBݷnݺ'B[C?~<6eBˇK.aw)Ai9F*//4 -j͛7_x?MT(ϟaSLU<@ؼy\..# uʕիW;;;ObsJhhѣSx=~5cIN S..#b 1gΜMTBB Q^ICbee+fPV9F ӴiP,\0))?#Bw~Z~L*M49!gdjOLLL?`k.''1c?~h?sBĈ9F(*''gٲevvv[l\vIKK^]F1BAPϞ=Cɟ^D`8h V0666lg#\ ׿{~8rlx]A{"""oժUh(!֭ԩS_6%b|C=|ҤI>>>g𰰰z*ߠ=;G !<<<>>ׯ?C?J*Ν3LȆ䏐>y?0atf($݅ E:-ZԶm?ܹsaMwԩSwؑM[n={lVwN2y7ƀƍwΝ5''M6igɓ'saJkkk`L8{=fSԛ`lR߾}1J$:hpqXO9FF3Դi>̟(ҽ{w ub@Wvm/X9ާOKKK \2Z4eddR͚5?⋖-[B4cƌar:v)]tN:v{}~2eE\\?cLW+""B<6lXŊ=ڵ`ӅINTTF^q3=z_&q Ņ?E$>D޹sGUJ(y&t`eeӧOǔ>>>)%%}D 3J$tZBB{'bo5Gy裏`4ԧ~ZZ5l*6ӰaC;v,Vze&] ,Bq ĩ˟r!82vb1o(T+”sΐ^ԬY5%Kfh4a(L &N ʎ`#G 8b)'L} MYnsQkXባPZ͟ZVfΜٚP۷ל: %[oi6f(MGPV\) PQʱ G>|8 ˱6mڠVXrttO=pE{{{삅e.[579_ҥK 'f˗ 3 ``(2+p|a OXs0vNNN 86lk(M?#`uȆB UD}j6aijhڿ7V^)7lؠٺsN A19> 8;wn\\~H֭[{-| <]UdCE+V}OD11@-2-[Y]re0l״iW0}֭11@1x%)_,Y;5oW_}%lٲVϞ=(нo_aJ'F1dj5s˗ڵ[x1?aP>zrA50F|;޽{` !0 #;v y6@C8qbS&NءC5OF"~MMM0OBPڵ >|8viɒ% y+Çԩ7fI*?8wر`ajݗ.] m;v,55WHKKCqM]bɓ!#BO\)b[~gb)T;w\l٤I00tR1F q߾}Ij_5췭Dq[HTT%cXDquVxX_5 E1TǍ5uo L3O>௃Ϟ={֬YeСeoh2qYj֯_eb7Kcaaa`E2>P%9!ޏ?f0iP`mmG m*6lHeYA ZnG m*PFϫWӅ ;7oڵ+%Aۻw~kG ;V4h%Ak۶ʕ+(atgΜ9G棄6c֦zAwwwooo>Jhn9o-_Jw( 4h@d(ѣƍ( :Ns ;Kdd$%AWޓ'O´ C鎍͉'( ɱ:,]JwUv>JhCqr eTz JG={m(ftiCґ۷o-[6//o 9{n?7JGΟ?_vm>JhI1s˗͛7 S #111?%9iӦ-[7M2ܹC|Вx腇 I@ґuߟZ"Ik׎&JG.\G -$rrrիwAP>d(2e'%D[hQ(| ud d8+(%.2oВT^ɓ|p u5dϨQի~QBK]1dߠ=޶|P8b @GGGiժռy(Q4K( 9ƧNdddT\YѿO Q7!5+dyBEFO=51`(Fnnnrr24o6lG"K.]RJff&@("+[۷o>J(2.dggcB?-)C:T^=* W\V%O?~z>J(2.?~Ɔ d(]h۶-%F~Btaƍ={䣄l?(@PG ٠RUv9Pd(]vww磄8q %JF=g>JȉJ*ݽ{o J j*>JȌ~ݛJ ]vݼy3%dFtt5!CB6m|/_l֬ٶmB9tW3gQB~`0ީS'>J(2.TX|>JLL@ҚǏ7H}%&Lpss㣄B Ci͍7*TG 7J 5 4ࣄѣǒ%K(PZݪU+>JȘ{ !Ci͖-[tG 75jԈ~WM& Ύfĉ3fࣄqpp⣄!Ci%dϑ#GիG,PZ_QB 4o||1d(_G %|ݻQBƐQFqqq|Pٕ+Wr @2T^|PNNN|+d(xY2e233B!S(R Ciݻw---_x7ʡUVT@Ҏ .ԬYbժU;w棄,!CiѣG6mG ERr@ҎݻwoߞJёPԷo_>J(CY[[ /_5^|GFF CiԩS'OG 2o޼QBfcĈ ,ࣄyfŊ322BNvڵ|P&={磄 CiGǎwG em۶-[QBNy棄2yiZB6nݺΝ㣄b8q"=Yΐ˗ʕKOOŒhee7 *o%?e J RRRTG _QB >>/%Ν;w*Tpmd(-طoO?G ӫW/yB҂=zQBlٲM6|d(-X|СC(|rrrW7Ɔ 3g?~<%L777N !Ciرcg͚G ѣק'Fɍb81fC.]&LG 0/@ ot4ԕ+W:u ADIDUZYYaɋtiܸ1]cMЊ+FEE ~=>)LR B [ ӰaSNQ„_(O`Vhm2e f@JRSS(aBݛz>UAC>|C={ NNNv|aBWP~'8 |ֆ,L7o/_&G׮](ODB**磄ԱcG>J+Vx "VPϟ'ϟ?לLl۶?ࣄ)bkkxb>J CCע >%KhN\ G SW#zԁ!)* 9B?ȑ#(aTV-99o CVaHl(}ݻTdI͉(a8::ҷ FVaP#XlYΝ;ÇW^%5Ν;5t钭m5Zn]d e^^&M0ejN?LfJ={ƕUh  nUTUTai¦?̵~嗗/_٫W/nlŋ VmU(<}ig0 CbCYZZ(Qf͚eggc i&MCCC~G;;;-UM6%tmo[n-lh׮Io8;;{{{QBhĆGϞ=4۳Y?^fMLA@Ux :tEVX1eʔ+W+&Pz,2aD”7㣄٤I>JPДtFbbxb߾}^^^={\2E0Xn  kꫯT\9״lْMqFa2=ҥK|0]peQFBB@HMVaHl(rP… iiikY4hРL2zG}$Lc.l&xw54Yt֪Pakݻ7&+h~ `߽{w~ ~Z[haa(Fnn={ biiEĚ>sSGddd`{!5jG )* =(X#Z!O?T0JbM6 ?B]=y0zWǏg#J} 5 ~>J:ժU[o CbCȯi4ioW``Rݺu_ot/@+jժe ׳Y0x6l(WVZ}?;F'nnnӦM㣄h չsgvA@@f/S^.]:==O5)U޽{x?ӧ Dxxx(aDEEIh4:x``>vؑ9YPP)TOn:y$2))M0rȟ~EZsi.˗Fm۶PA֧O>J(M}SUuvv棄yd7"V!C k&M⣄y1>jv>JHUPEbĈ ,ࣄySjU|< HڮYfÐ!CϟG  Htqǎ|0m&|ŝD 1/Lx Hԭ[07G ) ͼ|\rRlٰa ܿ7Ľ{ʗ/7F*d7sժUQܹ(QlDBz3}%̏˗ۗg̾}~g>J׮]X"{D _!/8уfɏ?8777jqq _Y&44 .[ +WG fَ@5OhUP"##RJG z{{O0A30 $Lg֨QBTj4&!F*d(N:U\3f  Z4&FÆ /*W'!C*d( 9x ~ a,&Ϲs<<<Ǎ8{d(SLv= "V!C`WlY\O"ҵk͛7RR6*,~ZT*?'ar"V!CeϞ=P'lٲܕ#b3T^^^JJׯ_?k,ooѣGSo쐂"l2L0/`iX&t}z˖-0!CGFQa"VQ(QL:s=l-[^`_GN $Ġ '$8?ï^wY~ȑ+V aӧ~fXEIz9֋Zɵk^~?8 {}aw&P,ڵ3tر 788qk43 ߸|wwwxΝIrJ;;;q8D";CEFF=gƠ7'ξ}01c@0Cqu> W1eς ͛w}~H&Ҥʗ0bMiiRk5TAGxX:vڬY3goo\֭q^~}ŊTRdee رᄈPSR% C/v|˗/ uu[[>.]W^B= bcc1-Zjȑ#-[dWhJKK裏&%%v-YB+8"5k}4B@׬YLc_ 8{lX}Çg2JQ¸hOٹ3eʔ:u ;w-81."V1p/A:Ѳ˜b*U|ӧOGaÆ)m۶%K"poܸ1Z*VWtѣL޽~m`(dO NNN~~~X&ԟc7+ .욚+8XZZN6ǧnݺ88.h۷/"...8j䰛Z>jժժU M9%èQ[ˆ zALpօdC&@Ԯ]j4hhoo%J"dj۶-uttDSrr2Vg!i;w]v?K)Ef"K3fm+ś#+"V1㱫f(TIB]a=>}o=-.qHeHw߽|ԩS1f"6m&!ARׂ;T~# 4[%XBTT2 /3-4>)ҥ z/_&]]]j(zP3zzREES?|Á:Kh:w;#J'CqΝ;/'Ok ^;vLhE RӦjժ{c]˖-ERs b#whe(rɱhѢ%KCVRe6v7n| ԯW&@P7ߡѣG٨WO>Ǒ~:=>ppT6lc,GC$==}رx￳6Rg^#œ%b(,k׮?H;wqaE1ј`᏷NXȆ o1P ;Y1[៌P.]Zhjݺ5\t)(aTd3z w\ ?ؙ# ФIṬ0Є&\\\4fcc#.Ly?C׬YÚD FfdJ7Fb, \ŷoi] E` >AϘ#>vrrRГ ͊{al'&XE^bc,o>zC1˖-8p`PP7q\< {nUhWǖϙ3gذa]@?(ENSF+uV``;ưA'"V݌1<^c|4߀\'O_ruEEE=?*G*6#==}ߜ|G){w9qƍիW+,NHѣGgΜiر[nXEbQ4+!!o=1ch\O<ٻw1c`o޼⻏(YYY111-rttDg.^ҥK|w (PV̛7̙3qP~.Ŀwj &888`Hrcǎ"?:u*j%''e˖={V %;w.H۷߼y?>ۉ6c˱Hdx|r Qׯ=n6ܹs'66vÆ 'OFv 6 Wp"VQp`lق420A2ۃ¶a Zl3D1x#Q,~۵kӧMJJJXjĉՌ5߾}S*`(M0޳gϜ9sq AC+WGXo`]k6`K=*lހ&\ .\8rH۶mINN̸x"JExvuuuRݙ5kVHH&y!bS3Gvvv\\Onݺ{:tcum1,kFk7067nYsիWa($|9sqXnDv^ ׮]+WDP`iZ.h ]҄\BWx>r+@rssqq1¥ ,SBh"bJL0/RG 8^xquT.87n fԩSO#L}qVa&knaX E(Bj׮}iBN8Q^=[DDB"]5k3%tB*d(Ѕ_~e۶m| Bk˗/RB'DB" ҥ %tE*d([[[???>J芈UP/^U=BBDB"y1"UPA`LJA*d((k׮QBX EG = b2AÇ˗/Oe  ޞ˗'No댈UPQ([/.\0`ׯ D  eȐ!eʔ߿?ߠ&77ۻjժ| "V!CD@@+V,nԨ΅˗sMX E\fM$|n0[f e˖E(RoD*d((+++$|@脈UPQ((ʕ+ǔ,--ً˧S"b2Aw bS#UP!F=ʔ)# /^ODBqU^])b#b2AW~}fVZ?UP!ݻի NX Eb$&&ZZZ?UPׯC(111լ]vk܆qvvf/# ¼Xdڱ lD!X EȝgϞ?~xDDDHH0a...jYtm۶_͡C.INNC5*- ^;l!X[2Z^[a梆m0~{;l~X EȂ<(@6m4#G28991'|@@͛aΝ;Q F^`_G/ {}G󩼈UPyŋكZcÆ )s̙.۷L6ΝC[B8A/c7ߡG*d(Bx")) %';P/̛7C' s޽˟D>222N8>Dџo|+ y)˗/wsscJZhΝ;SRR3(]voY'y?Hs8jym5+-.^H]Ț?2rY.HM &[P)5AK .%(ٌ39yqu]s<99X E؁(,FYQQUE8 vee%F><<wwEU.*d(FL&` tn'{a4z=«: ^Ғ.\S\ `hh(bV:UP?c6+(66ڵkś $V!C=R[[j}}}:$Nv<=99988x͚5%V!C"H6nܸh"رc&8jjj-[?^Gb2EDD&74***&&'#X EEyyNkhh-f455%&& 'cX TWW/Ynjnn*Ɯ9s`0h4D⤱7ł`G7ʼnDM#sIBrS9rDǨQpX+=+.NHBr;W^!ˆ \<<<>sNUPEWW[osNq nFl?c`"@,V(|w8SĊK*..Fg h4?~\P8}4V;jCY(]駟 zh#V(`{8iO?@ O8Kj(k IBr/BCC1yg?ïiӦAcf̘!CBBBo6{wy'op%k׮' =2={&LZ^}Ջ/noogU*((`Uzk@@F SLӧ^{mFFk ;w.^K,Q5kօSyL|n>|8z /hO=J` :t|֭q4ZbN cNJ F}yq48Z X,P_hZ9""~~~~) ?2X .`Q-[Lk+`qbyfړ'Owecjj*o |`3gTX$cGG\3vXlGe͚51+#U1vݻypjܸq<É1v,XA# t^SoIIIq֭PwuԐ$oY#V$V!C ׯ'C.immE^j؊E>"G$M>ijjB Nuu5t:ua[[V.D|a0^|EԢWZMn^^YY'$$X0w0C ]B0B %1 | 0>VeHZhE! bZrgPQd" ]gCJ%NV`gϞ~MP+b_}+ǔC!,= q4;8r䈇*.@fѢEڂ x ^ V^q'Zi2^u-zcZnqD+0r@fkתw{C˗V$V!C }f_~Y(:uUy4i$JJ Ԇeeev(>>>+/zC%T.^^^BvAdy-0(DtZ+ )*cmu3T]]sJJ%+JX+g6mAӰa`Vq3 HRCqP6mBW>?~,N̙[,V>:fέӧr-֞ 2= SNɱWϞC 0@}?BVm[NԆ={Y5[wqĉ&..ƒ;vy}SG"6J1e}֘Ҫ{B<>>U<{jĈeKNNg̘[^^ & >)m0`A͝; P½o=z43εe D%1Tqq1x׮]hn:4F1rC\?t:xh˰h8&;8Nwul0 \WG$V!CWp<2D [6&] ,,{mGGYp^}@ODHB"HB"HB"HB"HB"HB"HB"HB"HB"HB"HB"HB"HB"HB"HB"HB"HB"HB"HB"HkC߿2bAM' "V`(2n8N'VA|-b =WA20 |  GAz}qq {!0 |ScT$ Izӟ6yAQAr1e( B"u!CẐp]PA.d( \P|IENDB`asciidoctor-kroki-0.10.0/spec/fixtures/alice.puml0000644000004100000410000000002414620142421022007 0ustar www-datawww-dataalice -> bob: hello asciidoctor-kroki-0.10.0/spec/asciidoctor_kroki_block_macro_spec.rb0000644000004100000410000001227014620142421025564 0ustar www-datawww-data# rubocop:disable Lint/ConstantDefinitionInBlock # frozen_string_literal: true require 'rspec_helper' require 'asciidoctor' require_relative '../lib/asciidoctor/extensions/asciidoctor_kroki' require_relative '../lib/asciidoctor/extensions/asciidoctor_kroki/extension' describe ::AsciidoctorExtensions::KrokiBlockMacroProcessor do context 'convert to html5' do it 'should catch exception if target is not readable' do input = <<~'ADOC' plantuml::spec/fixtures/missing.puml[svg,role=sequence] ADOC output = Asciidoctor.convert(input, standalone: false) (expect output).to eql %(

Unresolved block macro - plantuml::spec/fixtures/missing.puml[]

) end end context 'using a custom block macro' do it 'should disallow read' do # noinspection RubyClassModuleNamingConvention class DisallowReadKrokiBlockMacroProcessor < ::AsciidoctorExtensions::KrokiBlockMacroProcessor def read_allowed?(_target) false end end registry = Asciidoctor::Extensions.create do block_macro DisallowReadKrokiBlockMacroProcessor, 'plantuml' end input = <<~'ADOC' plantuml::spec/fixtures/alice.puml[svg,role=sequence] ADOC output = Asciidoctor.convert(input, standalone: false, extension_registry: registry) (expect output).to eql %() end it 'should allow read if target is not a URI' do # noinspection RubyClassModuleNamingConvention class DisallowUriReadKrokiBlockMacroProcessor < ::AsciidoctorExtensions::KrokiBlockMacroProcessor def read_allowed?(target) return false if ::Asciidoctor::Helpers.uriish?(target) true end end registry = Asciidoctor::Extensions.create do block_macro DisallowUriReadKrokiBlockMacroProcessor, 'plantuml' end input = <<~'ADOC' plantuml::https://domain.org/alice.puml[svg,role=sequence] plantuml::file://path/to/alice.puml[svg,role=sequence] plantuml::spec/fixtures/alice.puml[svg,role=sequence] ADOC output = Asciidoctor.convert(input, standalone: false, extension_registry: registry) (expect output).to eql %(
Diagram
) end it 'should override the resolve target method' do # noinspection RubyClassModuleNamingConvention class FixtureResolveTargetKrokiBlockMacroProcessor < ::AsciidoctorExtensions::KrokiBlockMacroProcessor def resolve_target_path(target) "spec/fixtures/#{target}" end end registry = Asciidoctor::Extensions.create do block_macro FixtureResolveTargetKrokiBlockMacroProcessor, 'plantuml' end input = <<~'ADOC' plantuml::alice.puml[svg,role=sequence] ADOC output = Asciidoctor.convert(input, standalone: false, extension_registry: registry) (expect output).to eql %(
Diagram
) end it 'should display unresolved block macro message when the target cannot be resolved' do # noinspection RubyClassModuleNamingConvention class UnresolvedTargetKrokiBlockMacroProcessor < ::AsciidoctorExtensions::KrokiBlockMacroProcessor def resolve_target_path(_target) nil end end registry = Asciidoctor::Extensions.create do block_macro UnresolvedTargetKrokiBlockMacroProcessor, 'plantuml' end input = <<~'ADOC' plantuml::alice.puml[svg,role=sequence] ADOC output = Asciidoctor.convert(input, standalone: false, extension_registry: registry) (expect output).to eql %(

Unresolved block macro - plantuml::alice.puml[]

) end it 'should override the unresolved block macro message' do # noinspection RubyClassModuleNamingConvention class CustomUnresolvedTargetMessageKrokiBlockMacroProcessor < ::AsciidoctorExtensions::KrokiBlockMacroProcessor def unresolved_block_macro_message(name, target) "*[ERROR: #{name}::#{target}[] - unresolved block macro]*" end end registry = Asciidoctor::Extensions.create do block_macro CustomUnresolvedTargetMessageKrokiBlockMacroProcessor, 'plantuml' end input = <<~'ADOC' plantuml::spec/fixtures/missing.puml[svg,role=sequence] ADOC output = Asciidoctor.convert(input, standalone: false, extension_registry: registry) (expect output).to eql %(

[ERROR: plantuml::spec/fixtures/missing.puml[] - unresolved block macro]

) end end end # rubocop:enable Lint/ConstantDefinitionInBlock asciidoctor-kroki-0.10.0/spec/require_spec.rb0000644000004100000410000000046014620142421021201 0ustar www-datawww-data# frozen_string_literal: true describe 'require' do it 'should require the library' do lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'asciidoctor-kroki' (expect Asciidoctor::Extensions.groups[:extgrp0]).to_not be_nil end end asciidoctor-kroki-0.10.0/spec/rspec_helper.rb0000644000004100000410000000044014620142421021164 0ustar www-datawww-data# frozen_string_literal: true RSpec.configure do |config| config.before(:suite) do FileUtils.rm(Dir.glob("#{__dir__}/../.asciidoctor/kroki/diag-*")) end config.after(:suite) do FileUtils.rm(Dir.glob("#{__dir__}/../.asciidoctor/kroki/diag-*")) unless ENV['DEBUG'] end end asciidoctor-kroki-0.10.0/spec/asciidoctor_kroki_spec.rb0000644000004100000410000002012314620142421023225 0ustar www-datawww-data# frozen_string_literal: true require 'rspec_helper' require 'asciidoctor' require_relative '../lib/asciidoctor/extensions/asciidoctor_kroki' describe ::AsciidoctorExtensions::KrokiBlockProcessor do context 'convert to html5' do it 'should convert a PlantUML block to an image' do input = <<~'ADOC' [plantuml] .... alice -> bob: hello .... ADOC output = Asciidoctor.convert(input, standalone: false) (expect output).to eql %(
Diagram
) end it 'should only pass diagram options as query parameters' do input = <<~'ADOC' [plantuml,alice-bob,svg,role=sequence,width=100,format=svg,link=https://asciidoc.org/,align=center,float=right,theme=bluegray] .... alice -> bob: hello .... ADOC output = Asciidoctor.convert(input, standalone: false) (expect output).to eql %(
alice-bob
) end it 'should use the title attribute as the alt value' do input = <<~'ADOC' [plantuml,title="Alice saying hello to Bob"] .... alice -> bob: hello .... ADOC output = Asciidoctor.convert(input, standalone: false) (expect output).to eql %(
Alice saying hello to Bob
Figure 1. Alice saying hello to Bob
) end it 'should use png if kroki-default-format is set to png' do input = <<~'ADOC' [plantuml] .... alice -> bob: hello .... ADOC output = Asciidoctor.convert(input, attributes: { 'kroki-default-format' => 'png' }, standalone: false) (expect output).to eql %(
Diagram
) end it 'should use svg if kroki-default-format is set to png and the diagram type does not support png' do input = <<~'ADOC' [nomnoml] .... [Pirate|eyeCount: Int|raid();pillage()| [beard]--[parrot] [beard]-:>[foul mouth] ] .... ADOC output = Asciidoctor.convert(input, attributes: { 'kroki-default-format' => 'png' }, standalone: false) (expect output).to eql %(
Diagram
) end it 'should include the plantuml-include file when safe mode is safe' do input = <<~'ADOC' [plantuml] .... alice -> bob: hello .... ADOC output = Asciidoctor.convert(input, attributes: { 'kroki-plantuml-include' => 'spec/fixtures/config.puml' }, standalone: false, safe: :safe) (expect output).to eql %(
Diagram
) end it 'should normalize plantuml-include path when safe mode is safe' do input = <<~'ADOC' [plantuml] .... alice -> bob: hello .... ADOC output = Asciidoctor.convert(input, attributes: { 'kroki-plantuml-include' => '../../../spec/fixtures/config.puml' }, standalone: false, safe: :safe) (expect output).to eql %(
Diagram
) end it 'should not include file which reside outside of the parent directory of the source when safe mode is safe' do input = <<~'ADOC' [plantuml] .... alice -> bob: hello .... ADOC output = Asciidoctor.convert(input, attributes: { 'kroki-plantuml-include' => '/etc/passwd' }, standalone: false, safe: :safe) (expect output).to eql %(
Diagram
) end it 'should not include file when safe mode is secure' do input = <<~'ADOC' [plantuml] .... alice -> bob: hello .... ADOC output = Asciidoctor.convert(input, attributes: { 'kroki-plantuml-include' => 'spec/fixtures/config.puml' }, standalone: false, safe: :secure) (expect output).to eql %(
Diagram
) end it 'should create SVG diagram in imagesdir if kroki-fetch-diagram is set' do input = <<~'ADOC' :imagesdir: .asciidoctor/kroki plantuml::spec/fixtures/alice.puml[svg,role=sequence] ADOC output = Asciidoctor.convert(input, attributes: { 'kroki-fetch-diagram' => '' }, standalone: false, safe: :safe) (expect output).to eql %(
Diagram
) end it 'should not fetch diagram when safe mode is secure' do input = <<~'ADOC' :imagesdir: .asciidoctor/kroki plantuml::spec/fixtures/alice.puml[svg,role=sequence] ADOC output = Asciidoctor.convert(input, attributes: { 'kroki-fetch-diagram' => '' }, standalone: false) (expect output).to eql %(
Diagram
) end it 'should create PNG diagram in imagesdir if kroki-fetch-diagram is set' do input = <<~'ADOC' :imagesdir: .asciidoctor/kroki plantuml::spec/fixtures/alice.puml[png,role=sequence] ADOC output = Asciidoctor.convert(input, attributes: { 'kroki-fetch-diagram' => '' }, standalone: false, safe: :safe) (expect output).to eql %(
Diagram
) end end context 'instantiate' do it 'should instantiate block processor without warning' do original_stderr = $stderr $stderr = StringIO.new ::AsciidoctorExtensions::KrokiBlockProcessor.new :plantuml, {} output = $stderr.string (expect output).to eql '' ensure $stderr = original_stderr end end end describe ::AsciidoctorExtensions::Kroki do it 'should return the list of supported diagrams' do diagram_names = ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES expect(diagram_names).to include('vegalite', 'plantuml', 'bytefield', 'bpmn', 'excalidraw', 'wavedrom', 'pikchr', 'structurizr', 'diagramsnet') end it 'should register the extension for the list of supported diagrams' do doc = Asciidoctor::Document.new registry = Asciidoctor::Extensions::Registry.new registry.activate doc ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES.each do |name| expect(registry.find_block_extension(name)).to_not be_nil, "expected block extension named '#{name}' to be registered" expect(registry.find_block_macro_extension(name)).to_not be_nil, "expected block macro extension named '#{name}' to be registered " end end end asciidoctor-kroki-0.10.0/spec/.rubocop.yml0000644000004100000410000000010314620142421020432 0ustar www-datawww-datainherit_from: - ../.rubocop.yml Metrics/BlockLength: Max: 500 asciidoctor-kroki-0.10.0/spec/asciidoctor_kroki_processor_spec.rb0000644000004100000410000000367314620142421025337 0ustar www-datawww-data# frozen_string_literal: true require 'rspec_helper' require 'asciidoctor' require_relative '../lib/asciidoctor/extensions/asciidoctor_kroki' describe '::AsciidoctorExtensions::KrokiProcessor' do it 'should return the images output directory (imagesoutdir attribute)' do doc = Asciidoctor.load('hello', attributes: { 'imagesoutdir' => '.asciidoctor/kroki/images', 'imagesdir' => '../images' }) output_dir_path = AsciidoctorExtensions::KrokiProcessor.send(:output_dir_path, doc) expect(output_dir_path).to eq '.asciidoctor/kroki/images' end it 'should return a path relative to output directory (to_dir option)' do doc = Asciidoctor.load('hello', to_dir: '.asciidoctor/kroki/relative', attributes: { 'imagesdir' => '../images' }) output_dir_path = AsciidoctorExtensions::KrokiProcessor.send(:output_dir_path, doc) expect(output_dir_path).to eq '.asciidoctor/kroki/relative/../images' end it 'should return a path relative to output directory (outdir attribute)' do doc = Asciidoctor.load('hello', attributes: { 'imagesdir' => 'resources/images', 'outdir' => '.asciidoctor/kroki/out' }) output_dir_path = AsciidoctorExtensions::KrokiProcessor.send(:output_dir_path, doc) expect(output_dir_path).to eq '.asciidoctor/kroki/out/resources/images' end it 'should return a path relative to the base directory (base_dir option)' do doc = Asciidoctor.load('hello', base_dir: '.asciidoctor/kroki', attributes: { 'imagesdir' => 'img' }) output_dir_path = AsciidoctorExtensions::KrokiProcessor.send(:output_dir_path, doc) expect(output_dir_path).to eq "#{::Dir.pwd}/.asciidoctor/kroki/img" end it 'should return a path relative to the base directory (default value is current working directory)' do doc = Asciidoctor.load('hello', attributes: { 'imagesdir' => 'img' }) output_dir_path = AsciidoctorExtensions::KrokiProcessor.send(:output_dir_path, doc) expect(output_dir_path).to eq "#{::Dir.pwd}/img" end end asciidoctor-kroki-0.10.0/Rakefile0000644000004100000410000000015714620142421016704 0ustar www-datawww-data# frozen_string_literal: true Dir.glob('tasks/*.rake').each { |file| load file } task default: %w[lint spec] asciidoctor-kroki-0.10.0/Gemfile0000644000004100000410000000010614620142421016524 0ustar www-datawww-data# frozen_string_literal: true source 'https://rubygems.org' gemspec asciidoctor-kroki-0.10.0/.ruby-version0000644000004100000410000000000614620142421017675 0ustar www-datawww-data3.2.0 asciidoctor-kroki-0.10.0/.rubocop.yml0000644000004100000410000000066714620142421017517 0ustar www-datawww-dataAllCops: TargetRubyVersion: 2.7 SuggestExtensions: false NewCops: enable Style/Encoding: Enabled: false Layout/EndOfLine: EnforcedStyle: lf Layout/LineLength: Max: 180 Metrics/ClassLength: Max: 150 Metrics/MethodLength: Max: 50 Metrics/CyclomaticComplexity: Max: 10 Metrics/PerceivedComplexity: Max: 10 Metrics/AbcSize: Max: 31 Metrics/ParameterLists: Max: 7 Gemspec/RequiredRubyVersion: Enabled: false asciidoctor-kroki-0.10.0/asciidoctor-kroki.gemspec0000644000004100000410000000204314620142421022220 0ustar www-datawww-data# frozen_string_literal: true require_relative 'lib/asciidoctor/extensions/asciidoctor_kroki/version' Gem::Specification.new do |s| s.name = 'asciidoctor-kroki' s.version = Asciidoctor::AsciidoctorKroki::VERSION s.summary = 'Asciidoctor extension to convert diagrams to images using Kroki' s.description = 'An extension for Asciidoctor to convert diagrams to images using https://kroki.io' s.authors = ['Guillaume Grossetie'] s.email = ['ggrossetie@yuzutech.fr'] s.homepage = 'https://github.com/ggrossetie/asciidoctor-kroki' s.license = 'MIT' s.metadata = { 'bug_tracker_uri' => 'https://github.com/ggrossetie/asciidoctor-kroki/issues', 'source_code_uri' => 'https://github.com/ggrossetie/asciidoctor-kroki', 'rubygems_mfa_required' => 'true' } s.files = `git ls-files`.split($RS) s.require_paths = ['lib'] s.add_runtime_dependency 'asciidoctor', '~> 2.0' s.add_development_dependency 'rake', '~> 13.0.6' s.add_development_dependency 'rspec', '~> 3.10.0' s.add_development_dependency 'rubocop', '~> 1.30' end