asciidoctor-kroki 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b10096229def31407946a5f7e77eb57a991895d9407d334b6a4ca3dc7e8ba165
4
- data.tar.gz: 81497c2124169974c072a57c496b37d8cbd5e96b4793a22d59a3152fb1693c45
3
+ metadata.gz: 1d98287cf9a15751a442de9b1a07565c097206aae0912ca204ecaf4bdede4020
4
+ data.tar.gz: b1252225ed15a9f093d8a3c1d577e2bfa23c2abe7962981d638f49ea81d90a7b
5
5
  SHA512:
6
- metadata.gz: 03e1e7d5dc886c9e4ff9d7199f3289aa1a94d8b97a21209ba4ea9c4b505129646297bb62c02cab6390803b157a7a505e3af944ff533c49086af11927647776ce
7
- data.tar.gz: ad4cda7ce19c6ffa1223a224c1528c87e7b8864d554662f26a7534937f4bea49433e500373dad215feb09d71f748c84881ad720ea5c52765977383eb393a9f4c
6
+ metadata.gz: 46688eb160c567e33ba1f220ab229848a66874af0713962c339bc4d3b7d3352a5ef3f2f74e9c257bae6c579e03bf6c32cdf55e16f9b64d7b189aa103bf2d8550
7
+ data.tar.gz: 78a231f8b5921330aab30a2cd5c4f56ab84f917e31dc4cc85d2eb126cec84f04bd52756db2ff1fd8991116086b1100184c0644f35929fadb8ae49f95806e1248
data/.rubocop.yml CHANGED
@@ -1,10 +1,15 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.7
3
+ SuggestExtensions: false
4
+ NewCops: enable
5
+
1
6
  Style/Encoding:
2
7
  Enabled: false
3
8
 
4
9
  Layout/EndOfLine:
5
10
  EnforcedStyle: lf
6
11
 
7
- Metrics/LineLength:
12
+ Layout/LineLength:
8
13
  Max: 180
9
14
 
10
15
  Metrics/ClassLength:
@@ -20,7 +25,10 @@ Metrics/PerceivedComplexity:
20
25
  Max: 10
21
26
 
22
27
  Metrics/AbcSize:
23
- Max: 30
28
+ Max: 31
24
29
 
25
30
  Metrics/ParameterLists:
26
31
  Max: 7
32
+
33
+ Gemspec/RequiredRubyVersion:
34
+ Enabled: false
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.5
1
+ 3.1.2
data/Gemfile.lock CHANGED
@@ -1,52 +1,57 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- asciidoctor-kroki (0.5.0)
4
+ asciidoctor-kroki (0.6.0)
5
5
  asciidoctor (~> 2.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
10
  asciidoctor (2.0.11)
11
- ast (2.4.1)
12
- diff-lcs (1.3)
13
- jaro_winkler (1.5.4)
14
- parallel (1.19.1)
15
- parser (2.7.1.3)
16
- ast (~> 2.4.0)
17
- rainbow (3.0.0)
18
- rake (12.3.3)
19
- rspec (3.8.0)
20
- rspec-core (~> 3.8.0)
21
- rspec-expectations (~> 3.8.0)
22
- rspec-mocks (~> 3.8.0)
23
- rspec-core (3.8.2)
24
- rspec-support (~> 3.8.0)
25
- rspec-expectations (3.8.6)
11
+ ast (2.4.2)
12
+ diff-lcs (1.4.4)
13
+ parallel (1.22.1)
14
+ parser (3.1.2.0)
15
+ ast (~> 2.4.1)
16
+ rainbow (3.1.1)
17
+ rake (13.0.6)
18
+ regexp_parser (2.5.0)
19
+ rexml (3.2.5)
20
+ rspec (3.10.0)
21
+ rspec-core (~> 3.10.0)
22
+ rspec-expectations (~> 3.10.0)
23
+ rspec-mocks (~> 3.10.0)
24
+ rspec-core (3.10.1)
25
+ rspec-support (~> 3.10.0)
26
+ rspec-expectations (3.10.1)
26
27
  diff-lcs (>= 1.2.0, < 2.0)
27
- rspec-support (~> 3.8.0)
28
- rspec-mocks (3.8.2)
28
+ rspec-support (~> 3.10.0)
29
+ rspec-mocks (3.10.2)
29
30
  diff-lcs (>= 1.2.0, < 2.0)
30
- rspec-support (~> 3.8.0)
31
- rspec-support (3.8.3)
32
- rubocop (0.74.0)
33
- jaro_winkler (~> 1.5.1)
31
+ rspec-support (~> 3.10.0)
32
+ rspec-support (3.10.2)
33
+ rubocop (1.30.0)
34
34
  parallel (~> 1.10)
35
- parser (>= 2.6)
35
+ parser (>= 3.1.0.0)
36
36
  rainbow (>= 2.2.2, < 4.0)
37
+ regexp_parser (>= 1.8, < 3.0)
38
+ rexml (>= 3.2.5, < 4.0)
39
+ rubocop-ast (>= 1.18.0, < 2.0)
37
40
  ruby-progressbar (~> 1.7)
38
- unicode-display_width (>= 1.4.0, < 1.7)
39
- ruby-progressbar (1.10.1)
40
- unicode-display_width (1.6.1)
41
+ unicode-display_width (>= 1.4.0, < 3.0)
42
+ rubocop-ast (1.18.0)
43
+ parser (>= 3.1.1.0)
44
+ ruby-progressbar (1.11.0)
45
+ unicode-display_width (2.1.0)
41
46
 
42
47
  PLATFORMS
43
48
  ruby
44
49
 
45
50
  DEPENDENCIES
46
51
  asciidoctor-kroki!
47
- rake (~> 12.3.2)
48
- rspec (~> 3.8.0)
49
- rubocop (~> 0.74.0)
52
+ rake (~> 13.0.6)
53
+ rspec (~> 3.10.0)
54
+ rubocop (~> 1.30)
50
55
 
51
56
  BUNDLED WITH
52
- 2.2.17
57
+ 2.3.15
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'lib/asciidoctor/extensions/asciidoctor_kroki/version'
4
+
3
5
  Gem::Specification.new do |s|
4
6
  s.name = 'asciidoctor-kroki'
5
- s.version = '0.5.0'
7
+ s.version = Asciidoctor::AsciidoctorKroki::VERSION
6
8
  s.summary = 'Asciidoctor extension to convert diagrams to images using Kroki'
7
9
  s.description = 'An extension for Asciidoctor to convert diagrams to images using https://kroki.io'
8
10
 
@@ -12,15 +14,15 @@ Gem::Specification.new do |s|
12
14
  s.license = 'MIT'
13
15
  s.metadata = {
14
16
  'bug_tracker_uri' => 'https://github.com/Mogztter/asciidoctor-kroki/issues',
15
- 'source_code_uri' => 'https://github.com/Mogztter/asciidoctor-kroki'
17
+ 'source_code_uri' => 'https://github.com/Mogztter/asciidoctor-kroki',
18
+ 'rubygems_mfa_required' => 'true'
16
19
  }
17
20
  s.files = `git ls-files`.split($RS)
18
- s.test_files = s.files.grep(%r{^(test|spec|features|tasks)/})
19
21
  s.require_paths = ['lib']
20
22
 
21
23
  s.add_runtime_dependency 'asciidoctor', '~> 2.0'
22
24
 
23
- s.add_development_dependency 'rake', '~> 12.3.2'
24
- s.add_development_dependency 'rspec', '~> 3.8.0'
25
- s.add_development_dependency 'rubocop', '~> 0.74.0'
25
+ s.add_development_dependency 'rake', '~> 13.0.6'
26
+ s.add_development_dependency 'rspec', '~> 3.10.0'
27
+ s.add_development_dependency 'rubocop', '~> 1.30'
26
28
  end
@@ -38,6 +38,7 @@ module AsciidoctorExtensions
38
38
  # A block macro extension that converts a diagram into an image.
39
39
  #
40
40
  class KrokiBlockMacroProcessor < Asciidoctor::Extensions::BlockMacroProcessor
41
+ include Asciidoctor::Logging
41
42
  use_dsl
42
43
 
43
44
  name_positional_attributes 'format'
@@ -61,14 +62,14 @@ module AsciidoctorExtensions
61
62
  end
62
63
 
63
64
  unless (path = resolve_target_path(target))
64
- logger.error "#{diagram_type} block macro not found: #{target}."
65
- create_block(parent, 'paragraph', unresolved_block_macro_message(diagram_type, target), {})
65
+ logger.error message_with_context "#{diagram_type} block macro not found: #{target}.", source_location: parent.document.reader.cursor_at_mark
66
+ return create_block(parent, 'paragraph', unresolved_block_macro_message(diagram_type, target), {})
66
67
  end
67
68
 
68
69
  begin
69
70
  diagram_text = read(path)
70
- rescue => e # rubocop:disable RescueStandardError
71
- logger.error "Failed to read #{diagram_type} file: #{path}. #{e}."
71
+ rescue => e # rubocop:disable Style/RescueStandardError
72
+ logger.error message_with_context "Failed to read #{diagram_type} file: #{path}. #{e}.", source_location: parent.document.reader.cursor_at_mark
72
73
  return create_block(parent, 'paragraph', unresolved_block_macro_message(diagram_type, path), {})
73
74
  end
74
75
  KrokiProcessor.process(self, parent, attrs, diagram_type, diagram_text, @logger)
@@ -89,9 +90,9 @@ module AsciidoctorExtensions
89
90
  def read(target)
90
91
  if target.start_with?('http://') || target.start_with?('https://')
91
92
  require 'open-uri'
92
- URI.open(target, &:read)
93
+ ::OpenURI.open_uri(target, &:read)
93
94
  else
94
- File.open(target, &:read)
95
+ File.read(target, mode: 'rb:utf-8:utf-8')
95
96
  end
96
97
  end
97
98
 
@@ -126,15 +127,19 @@ module AsciidoctorExtensions
126
127
  vega
127
128
  vegalite
128
129
  wavedrom
130
+ structurizr
129
131
  ].freeze
130
132
  end
131
133
 
132
134
  # Internal processor
133
135
  #
134
136
  class KrokiProcessor
137
+ include Asciidoctor::Logging
138
+
135
139
  TEXT_FORMATS = %w[txt atxt utxt].freeze
136
140
 
137
141
  class << self
142
+ # rubocop:disable Metrics/AbcSize
138
143
  def process(processor, parent, attrs, diagram_type, diagram_text, logger)
139
144
  doc = parent.document
140
145
  diagram_text = prepend_plantuml_config(diagram_text, diagram_type, doc, logger)
@@ -146,12 +151,17 @@ module AsciidoctorExtensions
146
151
  title = attrs.delete('title')
147
152
  caption = attrs.delete('caption')
148
153
  attrs.delete('opts')
149
- role = attrs['role']
150
154
  format = get_format(doc, attrs, diagram_type)
151
- attrs['role'] = get_role(format, role)
155
+ attrs['role'] = get_role(format, attrs['role'])
152
156
  attrs['format'] = format
153
- kroki_diagram = KrokiDiagram.new(diagram_type, format, diagram_text)
154
- kroki_client = KrokiClient.new(server_url(doc), http_method(doc), KrokiHttpClient, logger, max_uri_length(doc))
157
+ kroki_diagram = KrokiDiagram.new(diagram_type, format, diagram_text, attrs['target'])
158
+ kroki_client = KrokiClient.new({
159
+ server_url: server_url(doc),
160
+ http_method: http_method(doc),
161
+ max_uri_length: max_uri_length(doc),
162
+ source_location: doc.reader.cursor_at_mark,
163
+ http_client: KrokiHttpClient
164
+ }, logger)
155
165
  if TEXT_FORMATS.include?(format)
156
166
  text_content = kroki_client.text_content(kroki_diagram)
157
167
  block = processor.create_block(parent, 'literal', text_content, attrs)
@@ -164,6 +174,7 @@ module AsciidoctorExtensions
164
174
  block.assign_caption(caption, 'figure')
165
175
  block
166
176
  end
177
+ # rubocop:enable Metrics/AbcSize
167
178
 
168
179
  private
169
180
 
@@ -174,9 +185,10 @@ module AsciidoctorExtensions
174
185
  plantuml_include_path = doc.normalize_system_path(doc.attr('kroki-plantuml-include'))
175
186
  if ::File.readable? plantuml_include_path
176
187
  config = File.read(plantuml_include_path)
177
- diagram_text = config + "\n" + diagram_text
188
+ diagram_text = "#{config}\n#{diagram_text}"
178
189
  else
179
- logger.warn "Unable to read plantuml-include. File not found or not readable: #{plantuml_include_path}."
190
+ logger.warn message_with_context "Unable to read plantuml-include. File not found or not readable: #{plantuml_include_path}.",
191
+ source_location: doc.reader.cursor_at_mark
180
192
  end
181
193
  end
182
194
  diagram_text
@@ -205,13 +217,13 @@ module AsciidoctorExtensions
205
217
  end
206
218
 
207
219
  def get_format(doc, attrs, diagram_type)
208
- format = attrs['format'] || 'svg'
209
- # The JavaFX preview doesn't support SVG well, therefore we'll use PNG format...
210
- if doc.attr?('env-idea') && format == 'svg'
211
- # ... unless the diagram library does not support PNG as output format!
220
+ format = attrs['format'] || doc.attr('kroki-default-format') || 'svg'
221
+ if format == 'png'
222
+ # redirect PNG format to SVG if the diagram library only supports SVG as output format.
223
+ # this is useful when the default format has been set to PNG
212
224
  # Currently, mermaid, nomnoml, svgbob, wavedrom only support SVG as output format.
213
- svg_only_diagram_types = %w[:mermaid :nomnoml :svgbob :wavedrom]
214
- format = 'png' unless svg_only_diagram_types.include?(diagram_type)
225
+ svg_only_diagram_types = %i[mermaid nomnoml svgbob wavedrom]
226
+ format = 'svg' if svg_only_diagram_types.include?(diagram_type)
215
227
  end
216
228
  format
217
229
  end
@@ -240,10 +252,9 @@ module AsciidoctorExtensions
240
252
  images_dir = doc.attr('imagesdir', '')
241
253
  if (images_output_dir = doc.attr('imagesoutdir'))
242
254
  images_output_dir
243
- elsif (out_dir = doc.attr('outdir'))
255
+ # the nested document logic will become obsolete once https://github.com/asciidoctor/asciidoctor/commit/7edc9da023522be67b17e2a085d72e056703a438 is released
256
+ elsif (out_dir = doc.attr('outdir') || (doc.nested? ? doc.parent_document : doc).options[:to_dir])
244
257
  File.join(out_dir, images_dir)
245
- elsif (to_dir = doc.attr('to_dir'))
246
- File.join(to_dir, images_dir)
247
258
  else
248
259
  File.join(doc.base_dir, images_dir)
249
260
  end
@@ -258,14 +269,13 @@ module AsciidoctorExtensions
258
269
  require 'zlib'
259
270
  require 'digest'
260
271
 
261
- attr_reader :type
262
- attr_reader :text
263
- attr_reader :format
272
+ attr_reader :type, :text, :format, :target
264
273
 
265
- def initialize(type, format, text)
274
+ def initialize(type, format, text, target = nil)
266
275
  @text = text
267
276
  @type = type
268
277
  @format = format
278
+ @target = target
269
279
  end
270
280
 
271
281
  def get_diagram_uri(server_url)
@@ -278,23 +288,21 @@ module AsciidoctorExtensions
278
288
 
279
289
  def save(output_dir_path, kroki_client)
280
290
  diagram_url = get_diagram_uri(kroki_client.server_url)
281
- diagram_name = "diag-#{Digest::SHA256.hexdigest diagram_url}.#{@format}"
291
+ diagram_name = "#{@target || 'diag'}-#{Digest::SHA256.hexdigest diagram_url}.#{@format}"
282
292
  file_path = File.join(output_dir_path, diagram_name)
283
- encoding = if @format == 'txt' || @format == 'atxt' || @format == 'utxt'
293
+ encoding = case @format
294
+ when 'txt', 'atxt', 'utxt', 'svg'
284
295
  'utf8'
285
- elsif @format == 'svg'
286
- 'binary'
287
296
  else
288
297
  'binary'
289
298
  end
290
299
  # file is either (already) on the file system or we should read it from Kroki
291
- contents = File.exist?(file_path) ? File.open(file_path, &:read) : kroki_client.get_image(self, encoding)
292
- FileUtils.mkdir_p(output_dir_path)
293
- if encoding == 'binary'
294
- File.binwrite(file_path, contents)
295
- else
296
- File.write(file_path, contents)
300
+ unless File.exist?(file_path)
301
+ contents = kroki_client.get_image(self, encoding)
302
+ FileUtils.mkdir_p(output_dir_path)
303
+ File.write(file_path, contents, mode: 'wb')
297
304
  end
305
+
298
306
  diagram_name
299
307
  end
300
308
 
@@ -303,12 +311,12 @@ module AsciidoctorExtensions
303
311
  def _join_uri_segments(base, *uris)
304
312
  segments = []
305
313
  # remove trailing slashes
306
- segments.push(base.gsub(%r{[/]+$}, ''))
314
+ segments.push(base.gsub(%r{/+$}, ''))
307
315
  segments.concat(uris.map do |uri|
308
316
  # remove leading and trailing slashes
309
317
  uri.to_s
310
- .gsub(%r{^[/]+}, '')
311
- .gsub(%r{[/]+$}, '')
318
+ .gsub(%r{^/+}, '')
319
+ .gsub(%r{/+$}, '')
312
320
  end)
313
321
  segments.join('/')
314
322
  end
@@ -317,21 +325,23 @@ module AsciidoctorExtensions
317
325
  # Kroki client
318
326
  #
319
327
  class KrokiClient
320
- attr_reader :server_url
321
- attr_reader :method
322
- attr_reader :max_uri_length
328
+ include Asciidoctor::Logging
329
+
330
+ attr_reader :server_url, :method, :max_uri_length
323
331
 
324
332
  SUPPORTED_HTTP_METHODS = %w[get post adaptive].freeze
325
333
 
326
- def initialize(server_url, http_method, http_client, logger = ::Asciidoctor::LoggerManager.logger, max_uri_length = 4000)
327
- @server_url = server_url
328
- @max_uri_length = max_uri_length
329
- @http_client = http_client
330
- method = (http_method || 'adaptive').downcase
334
+ def initialize(opts, logger = ::Asciidoctor::LoggerManager.logger)
335
+ @server_url = opts[:server_url]
336
+ @max_uri_length = opts.fetch(:max_uri_length, 4000)
337
+ @http_client = opts[:http_client]
338
+ method = opts.fetch(:http_method, 'adaptive').downcase
331
339
  if SUPPORTED_HTTP_METHODS.include?(method)
332
340
  @method = method
333
341
  else
334
- logger.warn "Invalid value '#{method}' for kroki-http-method attribute. The value must be either: 'get', 'post' or 'adaptive'. Proceeding using: 'adaptive'."
342
+ logger.warn message_with_context "Invalid value '#{method}' for kroki-http-method attribute. The value must be either: " \
343
+ "'get', 'post' or 'adaptive'. Proceeding using: 'adaptive'.",
344
+ source_location: opts[:source_location]
335
345
  @method = 'adaptive'
336
346
  end
337
347
  end
@@ -372,12 +382,28 @@ module AsciidoctorExtensions
372
382
  require 'json'
373
383
 
374
384
  class << self
385
+ REFERER = "asciidoctor/kroki.rb/#{Asciidoctor::AsciidoctorKroki::VERSION}"
386
+
375
387
  def get(uri, _)
376
- ::OpenURI.open_uri(uri, 'r', &:read)
388
+ uri = URI(uri)
389
+ request = ::Net::HTTP::Get.new(uri)
390
+ request['referer'] = REFERER
391
+ ::Net::HTTP.start(
392
+ uri.hostname,
393
+ uri.port,
394
+ use_ssl: (uri.scheme == 'https')
395
+ ) do |http|
396
+ http.request(request).body
397
+ end
377
398
  end
378
399
 
379
400
  def post(uri, data, _)
380
- res = ::Net::HTTP.request_post(uri, data)
401
+ res = ::Net::HTTP.post(
402
+ URI(uri),
403
+ data,
404
+ 'Content-Type' => 'text/plain',
405
+ 'Referer' => REFERER
406
+ )
381
407
  res.body
382
408
  end
383
409
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor
4
+ module AsciidoctorKroki
5
+ VERSION = '0.6.0'
6
+ end
7
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
4
+ require_relative 'asciidoctor_kroki/version'
4
5
  require_relative 'asciidoctor_kroki/extension'
5
6
 
6
7
  Asciidoctor::Extensions.register do
@@ -1,3 +1,4 @@
1
+ # rubocop:disable Lint/ConstantDefinitionInBlock
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'rspec_helper'
@@ -88,7 +89,7 @@ describe ::AsciidoctorExtensions::KrokiBlockMacroProcessor do
88
89
  </div>
89
90
  </div>)
90
91
  end
91
- it 'should display unresolved block macro message when the traget cannot be resolved' do
92
+ it 'should display unresolved block macro message when the target cannot be resolved' do
92
93
  # noinspection RubyClassModuleNamingConvention
93
94
  class UnresolvedTargetKrokiBlockMacroProcessor < ::AsciidoctorExtensions::KrokiBlockMacroProcessor
94
95
  def resolve_target_path(_target)
@@ -103,7 +104,7 @@ describe ::AsciidoctorExtensions::KrokiBlockMacroProcessor do
103
104
  ADOC
104
105
  output = Asciidoctor.convert(input, standalone: false, extension_registry: registry)
105
106
  (expect output).to eql %(<div class="paragraph">
106
- <p>Unresolved block macro - plantuml::[]</p>
107
+ <p>Unresolved block macro - plantuml::alice.puml[]</p>
107
108
  </div>)
108
109
  end
109
110
  it 'should override the unresolved block macro message' do
@@ -126,3 +127,4 @@ describe ::AsciidoctorExtensions::KrokiBlockMacroProcessor do
126
127
  end
127
128
  end
128
129
  end
130
+ # rubocop:enable Lint/ConstantDefinitionInBlock
@@ -7,27 +7,27 @@ require_relative '../lib/asciidoctor/extensions/asciidoctor_kroki'
7
7
  describe ::AsciidoctorExtensions::KrokiClient do
8
8
  it 'should use adaptive method when http method is invalid' do
9
9
  kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient
10
- kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'patch', kroki_http_client)
10
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'patch', http_client: kroki_http_client)
11
11
  expect(kroki_client.method).to eq('adaptive')
12
12
  end
13
13
  it 'should use post method when http method is post' do
14
14
  kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient
15
- kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'POST', kroki_http_client)
15
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'POST', http_client: kroki_http_client)
16
16
  expect(kroki_client.method).to eq('post')
17
17
  end
18
18
  it 'should use get method when http method is get' do
19
19
  kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient
20
- kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'get', kroki_http_client)
20
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'get', http_client: kroki_http_client)
21
21
  expect(kroki_client.method).to eq('get')
22
22
  end
23
23
  it 'should use 4000 as the default max URI length' do
24
24
  kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient
25
- kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'get', kroki_http_client)
25
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'get', http_client: kroki_http_client)
26
26
  expect(kroki_client.max_uri_length).to eq(4000)
27
27
  end
28
28
  it 'should use a custom value as max URI length' do
29
29
  kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient
30
- kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'get', kroki_http_client, nil, 8000)
30
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'get', http_client: kroki_http_client, max_uri_length: 8000)
31
31
  expect(kroki_client.max_uri_length).to eq(8000)
32
32
  end
33
33
  it 'should get an image with POST request if the URI length is greater than the value configured' do
@@ -55,7 +55,7 @@ describe ::AsciidoctorExtensions::KrokiClient do
55
55
  'diagram-uri'
56
56
  end
57
57
  end.new('type', 'format', 'text')
58
- kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'adaptive', kroki_http_client, nil, 10)
58
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'adaptive', http_client: kroki_http_client, max_uri_length: 10)
59
59
  result = kroki_client.get_image(kroki_diagram, 'utf8')
60
60
  expect(result).to eq('POST http://localhost:8000/type/format - text')
61
61
  end
@@ -84,7 +84,7 @@ describe ::AsciidoctorExtensions::KrokiClient do
84
84
  'diagram-uri'
85
85
  end
86
86
  end.new('type', 'format', 'text')
87
- kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'adaptive', kroki_http_client, nil, 11)
87
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'http://localhost:8000', http_method: 'adaptive', http_client: kroki_http_client, max_uri_length: 11)
88
88
  result = kroki_client.get_image(kroki_diagram, 'utf8')
89
89
  expect(result).to eq('GET diagram-uri')
90
90
  end
@@ -28,11 +28,32 @@ describe ::AsciidoctorExtensions::KrokiDiagram do
28
28
  it 'should fetch a diagram from Kroki and save it to disk' do
29
29
  kroki_diagram = ::AsciidoctorExtensions::KrokiDiagram.new('plantuml', 'txt', ' alice -> bob: hello')
30
30
  kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient
31
- kroki_client = ::AsciidoctorExtensions::KrokiClient.new('https://kroki.io', 'get', kroki_http_client)
31
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'https://kroki.io', http_method: 'get', http_client: kroki_http_client)
32
32
  output_dir_path = "#{__dir__}/../.asciidoctor/kroki"
33
33
  diagram_name = kroki_diagram.save(output_dir_path, kroki_client)
34
34
  diagram_path = File.join(output_dir_path, diagram_name)
35
- expect(File.exist?(diagram_path)).to be_truthy, "expected diagram to be saved at #{diagram_path}"
35
+ expect(File.exist?(diagram_path)).to be_truthy, "diagram should be saved at: #{diagram_path}"
36
+ content = <<-TXT.chomp
37
+ ,-----. ,---.
38
+ |alice| |bob|
39
+ `--+--' `-+-'
40
+ | hello |
41
+ |-------------->|
42
+ ,--+--. ,-+-.
43
+ |alice| |bob|
44
+ `-----' `---'
45
+ TXT
46
+ expect(File.read(diagram_path).split("\n").map(&:rstrip).join("\n")).to eq(content)
47
+ end
48
+ it 'should fetch a diagram from Kroki and save it to disk using the target name' do
49
+ kroki_diagram = ::AsciidoctorExtensions::KrokiDiagram.new('plantuml', 'txt', ' alice -> bob: hello', 'hello-world')
50
+ kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient
51
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'https://kroki.io', http_method: 'get', http_client: kroki_http_client)
52
+ output_dir_path = "#{__dir__}/../.asciidoctor/kroki"
53
+ diagram_name = kroki_diagram.save(output_dir_path, kroki_client)
54
+ diagram_path = File.join(output_dir_path, diagram_name)
55
+ expect(diagram_name).to start_with('hello-world-'), "diagram name should use the target as a prefix, got: #{diagram_name}"
56
+ expect(File.exist?(diagram_path)).to be_truthy, "diagram should be saved at: #{diagram_path}"
36
57
  content = <<-TXT.chomp
37
58
  ,-----. ,---.
38
59
  |alice| |bob|
@@ -48,14 +69,16 @@ describe ::AsciidoctorExtensions::KrokiDiagram do
48
69
  it 'should fetch a diagram from Kroki with the same definition only once' do
49
70
  kroki_diagram = ::AsciidoctorExtensions::KrokiDiagram.new('plantuml', 'png', ' guillaume -> dan: hello')
50
71
  kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient
51
- kroki_client = ::AsciidoctorExtensions::KrokiClient.new('https://kroki.io', 'get', kroki_http_client)
72
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new(server_url: 'https://kroki.io', http_method: 'get', http_client: kroki_http_client)
52
73
  output_dir_path = "#{__dir__}/../.asciidoctor/kroki"
53
74
  # make sure that we are doing only one GET request
54
- expect(kroki_http_client).to receive(:get).once
75
+ diagram_contents = File.read("#{__dir__}/fixtures/plantuml-diagram.png", mode: 'rb')
76
+ expect(kroki_http_client).to receive(:get).once.and_return(diagram_contents)
55
77
  diagram_name = kroki_diagram.save(output_dir_path, kroki_client)
56
78
  diagram_path = File.join(output_dir_path, diagram_name)
57
- expect(File.exist?(diagram_path)).to be_truthy, "expected diagram to be saved at #{diagram_path}"
79
+ expect(File.exist?(diagram_path)).to be_truthy, "diagram should be saved at: #{diagram_path}"
58
80
  # calling again... should read the file from disk (and not do a GET request)
59
81
  kroki_diagram.save(output_dir_path, kroki_client)
82
+ expect(File.size(diagram_path)).to be_eql(diagram_contents.length), 'diagram should be fully saved on disk'
60
83
  end
61
84
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec_helper'
4
+ require 'asciidoctor'
5
+ require_relative '../lib/asciidoctor/extensions/asciidoctor_kroki'
6
+
7
+ describe '::AsciidoctorExtensions::KrokiProcessor' do
8
+ it 'should return the images output directory (imagesoutdir attribute)' do
9
+ doc = Asciidoctor.load('hello', attributes: { 'imagesoutdir' => '.asciidoctor/kroki/images', 'imagesdir' => '../images' })
10
+ output_dir_path = AsciidoctorExtensions::KrokiProcessor.send(:output_dir_path, doc)
11
+ expect(output_dir_path).to eq '.asciidoctor/kroki/images'
12
+ end
13
+ it 'should return a path relative to output directory (to_dir option)' do
14
+ doc = Asciidoctor.load('hello', to_dir: '.asciidoctor/kroki/relative', attributes: { 'imagesdir' => '../images' })
15
+ output_dir_path = AsciidoctorExtensions::KrokiProcessor.send(:output_dir_path, doc)
16
+ expect(output_dir_path).to eq '.asciidoctor/kroki/relative/../images'
17
+ end
18
+ it 'should return a path relative to output directory (outdir attribute)' do
19
+ doc = Asciidoctor.load('hello', attributes: { 'imagesdir' => 'resources/images', 'outdir' => '.asciidoctor/kroki/out' })
20
+ output_dir_path = AsciidoctorExtensions::KrokiProcessor.send(:output_dir_path, doc)
21
+ expect(output_dir_path).to eq '.asciidoctor/kroki/out/resources/images'
22
+ end
23
+ it 'should return a path relative to the base directory (base_dir option)' do
24
+ doc = Asciidoctor.load('hello', base_dir: '.asciidoctor/kroki', attributes: { 'imagesdir' => 'img' })
25
+ output_dir_path = AsciidoctorExtensions::KrokiProcessor.send(:output_dir_path, doc)
26
+ expect(output_dir_path).to eq "#{::Dir.pwd}/.asciidoctor/kroki/img"
27
+ end
28
+ it 'should return a path relative to the base directory (default value is current working directory)' do
29
+ doc = Asciidoctor.load('hello', attributes: { 'imagesdir' => 'img' })
30
+ output_dir_path = AsciidoctorExtensions::KrokiProcessor.send(:output_dir_path, doc)
31
+ expect(output_dir_path).to eq "#{::Dir.pwd}/img"
32
+ end
33
+ end
@@ -20,18 +20,33 @@ describe ::AsciidoctorExtensions::KrokiBlockProcessor do
20
20
  </div>
21
21
  </div>)
22
22
  end
23
- it 'should use png if env-idea is defined' do
23
+ it 'should use png if kroki-default-format is set to png' do
24
24
  input = <<~'ADOC'
25
25
  [plantuml]
26
26
  ....
27
27
  alice -> bob: hello
28
28
  ....
29
29
  ADOC
30
- output = Asciidoctor.convert(input, attributes: { 'env-idea' => '' }, standalone: false)
30
+ output = Asciidoctor.convert(input, attributes: { 'kroki-default-format' => 'png' }, standalone: false)
31
31
  (expect output).to eql %(<div class="imageblock kroki">
32
32
  <div class="content">
33
33
  <img src="https://kroki.io/plantuml/png/eNpLzMlMTlXQtVNIyk-yUshIzcnJBwA9iwZL" alt="Diagram">
34
34
  </div>
35
+ </div>)
36
+ end
37
+ it 'should use svg if kroki-default-format is set to png and the diagram type does not support png' do
38
+ input = <<~'ADOC'
39
+ [mermaid]
40
+ ....
41
+ graph TD;
42
+ A-->B;
43
+ ....
44
+ ADOC
45
+ output = Asciidoctor.convert(input, attributes: { 'kroki-default-format' => 'png' }, standalone: false)
46
+ (expect output).to eql %(<div class="imageblock kroki">
47
+ <div class="content">
48
+ <img src="https://kroki.io/mermaid/svg/eNpLL0osyFAIcbHmUlBw1NW1c7IGADLKBKY=" alt="Diagram">
49
+ </div>
35
50
  </div>)
36
51
  end
37
52
  it 'should include the plantuml-include file when safe mode is safe' do
@@ -41,10 +56,12 @@ describe ::AsciidoctorExtensions::KrokiBlockProcessor do
41
56
  alice -> bob: hello
42
57
  ....
43
58
  ADOC
44
- output = Asciidoctor.convert(input, attributes: { 'env-idea' => '', 'kroki-plantuml-include' => 'spec/fixtures/config.puml' }, standalone: false, safe: :safe)
59
+ output = Asciidoctor.convert(input,
60
+ attributes: { 'kroki-plantuml-include' => 'spec/fixtures/config.puml' },
61
+ standalone: false, safe: :safe)
45
62
  (expect output).to eql %(<div class="imageblock kroki">
46
63
  <div class="content">
47
- <img src="https://kroki.io/plantuml/png/eNorzs7MK0gsSsxVyM3Py0_OKMrPTVUoKSpN5eJKzMlMTlXQtVNIyk-yUshIzcnJBwCT9xBc" alt="Diagram">
64
+ <img src="https://kroki.io/plantuml/svg/eNorzs7MK0gsSsxVyM3Py0_OKMrPTVUoKSpN5eJKzMlMTlXQtVNIyk-yUshIzcnJBwCT9xBc" alt="Diagram">
48
65
  </div>
49
66
  </div>)
50
67
  end
@@ -55,10 +72,10 @@ describe ::AsciidoctorExtensions::KrokiBlockProcessor do
55
72
  alice -> bob: hello
56
73
  ....
57
74
  ADOC
58
- output = Asciidoctor.convert(input, attributes: { 'env-idea' => '', 'kroki-plantuml-include' => '../../../spec/fixtures/config.puml' }, standalone: false, safe: :safe)
75
+ output = Asciidoctor.convert(input, attributes: { 'kroki-plantuml-include' => '../../../spec/fixtures/config.puml' }, standalone: false, safe: :safe)
59
76
  (expect output).to eql %(<div class="imageblock kroki">
60
77
  <div class="content">
61
- <img src="https://kroki.io/plantuml/png/eNorzs7MK0gsSsxVyM3Py0_OKMrPTVUoKSpN5eJKzMlMTlXQtVNIyk-yUshIzcnJBwCT9xBc" alt="Diagram">
78
+ <img src="https://kroki.io/plantuml/svg/eNorzs7MK0gsSsxVyM3Py0_OKMrPTVUoKSpN5eJKzMlMTlXQtVNIyk-yUshIzcnJBwCT9xBc" alt="Diagram">
62
79
  </div>
63
80
  </div>)
64
81
  end
@@ -69,10 +86,10 @@ describe ::AsciidoctorExtensions::KrokiBlockProcessor do
69
86
  alice -> bob: hello
70
87
  ....
71
88
  ADOC
72
- output = Asciidoctor.convert(input, attributes: { 'env-idea' => '', 'kroki-plantuml-include' => '/etc/passwd' }, standalone: false, safe: :safe)
89
+ output = Asciidoctor.convert(input, attributes: { 'kroki-plantuml-include' => '/etc/passwd' }, standalone: false, safe: :safe)
73
90
  (expect output).to eql %(<div class="imageblock kroki">
74
91
  <div class="content">
75
- <img src="https://kroki.io/plantuml/png/eNpLzMlMTlXQtVNIyk-yUshIzcnJBwA9iwZL" alt="Diagram">
92
+ <img src="https://kroki.io/plantuml/svg/eNpLzMlMTlXQtVNIyk-yUshIzcnJBwA9iwZL" alt="Diagram">
76
93
  </div>
77
94
  </div>)
78
95
  end
@@ -83,10 +100,10 @@ describe ::AsciidoctorExtensions::KrokiBlockProcessor do
83
100
  alice -> bob: hello
84
101
  ....
85
102
  ADOC
86
- output = Asciidoctor.convert(input, attributes: { 'env-idea' => '', 'kroki-plantuml-include' => 'spec/fixtures/config.puml' }, standalone: false, safe: :secure)
103
+ output = Asciidoctor.convert(input, attributes: { 'kroki-plantuml-include' => 'spec/fixtures/config.puml' }, standalone: false, safe: :secure)
87
104
  (expect output).to eql %(<div class="imageblock kroki">
88
105
  <div class="content">
89
- <img src="https://kroki.io/plantuml/png/eNpLzMlMTlXQtVNIyk-yUshIzcnJBwA9iwZL" alt="Diagram">
106
+ <img src="https://kroki.io/plantuml/svg/eNpLzMlMTlXQtVNIyk-yUshIzcnJBwA9iwZL" alt="Diagram">
90
107
  </div>
91
108
  </div>)
92
109
  end
@@ -134,7 +151,7 @@ describe ::AsciidoctorExtensions::KrokiBlockProcessor do
134
151
  it 'should instantiate block processor without warning' do
135
152
  original_stderr = $stderr
136
153
  $stderr = StringIO.new
137
- ::AsciidoctorExtensions::KrokiBlockProcessor.new 'plantuml'.to_sym, {}
154
+ ::AsciidoctorExtensions::KrokiBlockProcessor.new :plantuml, {}
138
155
  output = $stderr.string
139
156
  (expect output).to eql ''
140
157
  ensure
@@ -146,7 +163,7 @@ end
146
163
  describe ::AsciidoctorExtensions::Kroki do
147
164
  it 'should return the list of supported diagrams' do
148
165
  diagram_names = ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES
149
- expect(diagram_names).to include('vegalite', 'plantuml', 'bytefield', 'bpmn', 'excalidraw', 'wavedrom', 'pikchr')
166
+ expect(diagram_names).to include('vegalite', 'plantuml', 'bytefield', 'bpmn', 'excalidraw', 'wavedrom', 'pikchr', 'structurizr')
150
167
  end
151
168
  it 'should register the extension for the list of supported diagrams' do
152
169
  doc = Asciidoctor::Document.new
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-kroki
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guillaume Grossetie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-05 00:00:00.000000000 Z
11
+ date: 2022-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -30,42 +30,42 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 12.3.2
33
+ version: 13.0.6
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 12.3.2
40
+ version: 13.0.6
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 3.8.0
47
+ version: 3.10.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 3.8.0
54
+ version: 3.10.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rubocop
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.74.0
61
+ version: '1.30'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.74.0
68
+ version: '1.30'
69
69
  description: An extension for Asciidoctor to convert diagrams to images using https://kroki.io
70
70
  email:
71
71
  - ggrossetie@yuzutech.fr
@@ -84,13 +84,16 @@ files:
84
84
  - lib/asciidoctor-kroki.rb
85
85
  - lib/asciidoctor/extensions/asciidoctor_kroki.rb
86
86
  - lib/asciidoctor/extensions/asciidoctor_kroki/extension.rb
87
+ - lib/asciidoctor/extensions/asciidoctor_kroki/version.rb
87
88
  - spec/.rubocop.yml
88
89
  - spec/asciidoctor_kroki_block_macro_spec.rb
89
90
  - spec/asciidoctor_kroki_client_spec.rb
90
91
  - spec/asciidoctor_kroki_diagram_spec.rb
92
+ - spec/asciidoctor_kroki_processor_spec.rb
91
93
  - spec/asciidoctor_kroki_spec.rb
92
94
  - spec/fixtures/alice.puml
93
95
  - spec/fixtures/config.puml
96
+ - spec/fixtures/plantuml-diagram.png
94
97
  - spec/require_spec.rb
95
98
  - spec/rspec_helper.rb
96
99
  - tasks/bundler.rake
@@ -102,6 +105,7 @@ licenses:
102
105
  metadata:
103
106
  bug_tracker_uri: https://github.com/Mogztter/asciidoctor-kroki/issues
104
107
  source_code_uri: https://github.com/Mogztter/asciidoctor-kroki
108
+ rubygems_mfa_required: 'true'
105
109
  post_install_message:
106
110
  rdoc_options: []
107
111
  require_paths:
@@ -121,16 +125,4 @@ rubygems_version: 3.1.6
121
125
  signing_key:
122
126
  specification_version: 4
123
127
  summary: Asciidoctor extension to convert diagrams to images using Kroki
124
- test_files:
125
- - spec/.rubocop.yml
126
- - spec/asciidoctor_kroki_block_macro_spec.rb
127
- - spec/asciidoctor_kroki_client_spec.rb
128
- - spec/asciidoctor_kroki_diagram_spec.rb
129
- - spec/asciidoctor_kroki_spec.rb
130
- - spec/fixtures/alice.puml
131
- - spec/fixtures/config.puml
132
- - spec/require_spec.rb
133
- - spec/rspec_helper.rb
134
- - tasks/bundler.rake
135
- - tasks/lint.rake
136
- - tasks/rspec.rake
128
+ test_files: []