asciidoctor-kroki 0.2.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f7ac5f1586d5aa5a1cf3f3031b0bcc1839e40681913f30722703011e133b6a72
4
- data.tar.gz: f10b7edc9d3e1092c35b07028b25255c6c2ae0921795d161dc542bdecc0b814f
3
+ metadata.gz: b10096229def31407946a5f7e77eb57a991895d9407d334b6a4ca3dc7e8ba165
4
+ data.tar.gz: 81497c2124169974c072a57c496b37d8cbd5e96b4793a22d59a3152fb1693c45
5
5
  SHA512:
6
- metadata.gz: 613ae500380df383cc2b05720795de55933d5813ebb10f70f9252454727fac61f05d7f9c581641c28be8ed1e9fd42b6dcb9bb86283de455f92e4c41e0e00a78e
7
- data.tar.gz: 25e547670dea5f121373ddc402b3740d33a6c1c31a006f3c2dd66dd5a753f4daa9d61aa7b6919543d7ec5c1b641b590a59c95b8de1b9419c6ffba2be7747a938
6
+ metadata.gz: 03e1e7d5dc886c9e4ff9d7199f3289aa1a94d8b97a21209ba4ea9c4b505129646297bb62c02cab6390803b157a7a505e3af944ff533c49086af11927647776ce
7
+ data.tar.gz: ad4cda7ce19c6ffa1223a224c1528c87e7b8864d554662f26a7534937f4bea49433e500373dad215feb09d71f748c84881ad720ea5c52765977383eb393a9f4c
data/.rubocop.yml CHANGED
@@ -1,8 +1,14 @@
1
1
  Style/Encoding:
2
2
  Enabled: false
3
3
 
4
+ Layout/EndOfLine:
5
+ EnforcedStyle: lf
6
+
4
7
  Metrics/LineLength:
5
- Max: 160
8
+ Max: 180
9
+
10
+ Metrics/ClassLength:
11
+ Max: 150
6
12
 
7
13
  Metrics/MethodLength:
8
14
  Max: 50
@@ -15,3 +21,6 @@ Metrics/PerceivedComplexity:
15
21
 
16
22
  Metrics/AbcSize:
17
23
  Max: 30
24
+
25
+ Metrics/ParameterLists:
26
+ Max: 7
data/Gemfile.lock CHANGED
@@ -1,62 +1,19 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- asciidoctor-kroki (0.2.0)
4
+ asciidoctor-kroki (0.5.0)
5
5
  asciidoctor (~> 2.0)
6
- asciidoctor-pdf (= 1.5.3)
7
6
 
8
7
  GEM
9
8
  remote: https://rubygems.org/
10
9
  specs:
11
- Ascii85 (1.0.3)
12
- addressable (2.7.0)
13
- public_suffix (>= 2.0.2, < 5.0)
14
- afm (0.2.2)
15
- asciidoctor (2.0.10)
16
- asciidoctor-pdf (1.5.3)
17
- asciidoctor (>= 1.5.3, < 3.0.0)
18
- concurrent-ruby (~> 1.1.0)
19
- prawn (~> 2.2.0)
20
- prawn-icon (~> 2.5.0)
21
- prawn-svg (~> 0.30.0)
22
- prawn-table (~> 0.2.0)
23
- prawn-templates (~> 0.1.0)
24
- safe_yaml (~> 1.0.0)
25
- thread_safe (~> 0.3.0)
26
- treetop (~> 1.6.0)
27
- ttfunk (~> 1.5.0, >= 1.5.1)
10
+ asciidoctor (2.0.11)
28
11
  ast (2.4.1)
29
- concurrent-ruby (1.1.6)
30
- css_parser (1.7.1)
31
- addressable
32
12
  diff-lcs (1.3)
33
- hashery (2.1.2)
34
13
  jaro_winkler (1.5.4)
35
14
  parallel (1.19.1)
36
15
  parser (2.7.1.3)
37
16
  ast (~> 2.4.0)
38
- pdf-core (0.7.0)
39
- pdf-reader (2.4.0)
40
- Ascii85 (~> 1.0.0)
41
- afm (~> 0.2.1)
42
- hashery (~> 2.0)
43
- ruby-rc4
44
- ttfunk
45
- polyglot (0.3.5)
46
- prawn (2.2.2)
47
- pdf-core (~> 0.7.0)
48
- ttfunk (~> 1.5)
49
- prawn-icon (2.5.0)
50
- prawn (>= 1.1.0, < 3.0.0)
51
- prawn-svg (0.30.0)
52
- css_parser (~> 1.6)
53
- prawn (>= 0.11.1, < 3)
54
- prawn-table (0.2.2)
55
- prawn (>= 1.3.0, < 3.0.0)
56
- prawn-templates (0.1.2)
57
- pdf-reader (~> 2.0)
58
- prawn (~> 2.2)
59
- public_suffix (4.0.5)
60
17
  rainbow (3.0.0)
61
18
  rake (12.3.3)
62
19
  rspec (3.8.0)
@@ -80,12 +37,6 @@ GEM
80
37
  ruby-progressbar (~> 1.7)
81
38
  unicode-display_width (>= 1.4.0, < 1.7)
82
39
  ruby-progressbar (1.10.1)
83
- ruby-rc4 (0.1.5)
84
- safe_yaml (1.0.5)
85
- thread_safe (0.3.6)
86
- treetop (1.6.10)
87
- polyglot (~> 0.3)
88
- ttfunk (1.5.1)
89
40
  unicode-display_width (1.6.1)
90
41
 
91
42
  PLATFORMS
@@ -98,4 +49,4 @@ DEPENDENCIES
98
49
  rubocop (~> 0.74.0)
99
50
 
100
51
  BUNDLED WITH
101
- 1.17.3
52
+ 2.2.17
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'asciidoctor-kroki'
5
- s.version = '0.2.0'
5
+ s.version = '0.5.0'
6
6
  s.summary = 'Asciidoctor extension to convert diagrams to images using Kroki'
7
7
  s.description = 'An extension for Asciidoctor to convert diagrams to images using https://kroki.io'
8
8
 
@@ -19,7 +19,6 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = ['lib']
20
20
 
21
21
  s.add_runtime_dependency 'asciidoctor', '~> 2.0'
22
- s.add_runtime_dependency 'asciidoctor-pdf', '1.5.3'
23
22
 
24
23
  s.add_development_dependency 'rake', '~> 12.3.2'
25
24
  s.add_development_dependency 'rspec', '~> 3.8.0'
@@ -15,11 +15,24 @@ module AsciidoctorExtensions
15
15
  on_context :listing, :literal
16
16
  name_positional_attributes 'target', 'format'
17
17
 
18
+ # @param name [String] name of the block macro (optional)
19
+ # @param config [Hash] a config hash (optional)
20
+ # - :logger a logger used to log warning and errors (optional)
21
+ #
22
+ def initialize(name = nil, config = {})
23
+ @logger = (config || {}).delete(:logger) { ::Asciidoctor::LoggerManager.logger }
24
+ super(name, config)
25
+ end
26
+
18
27
  def process(parent, reader, attrs)
19
28
  diagram_type = @name
20
29
  diagram_text = reader.string
21
- KrokiProcessor.process(self, parent, attrs, diagram_type, diagram_text)
30
+ KrokiProcessor.process(self, parent, attrs, diagram_type, diagram_text, @logger)
22
31
  end
32
+
33
+ protected
34
+
35
+ attr_reader :logger
23
36
  end
24
37
 
25
38
  # A block macro extension that converts a diagram into an image.
@@ -29,11 +42,48 @@ module AsciidoctorExtensions
29
42
 
30
43
  name_positional_attributes 'format'
31
44
 
45
+ # @param name [String] name of the block macro (optional)
46
+ # @param config [Hash] a config hash (optional)
47
+ # - :logger a logger used to log warning and errors (optional)
48
+ #
49
+ def initialize(name = nil, config = {})
50
+ @logger = (config || {}).delete(:logger) { ::Asciidoctor::LoggerManager.logger }
51
+ super(name, config)
52
+ end
53
+
32
54
  def process(parent, target, attrs)
33
55
  diagram_type = @name
34
56
  target = parent.apply_subs(target, [:attributes])
35
- diagram_text = read(target)
36
- KrokiProcessor.process(self, parent, attrs, diagram_type, diagram_text)
57
+
58
+ unless read_allowed?(target)
59
+ link = create_inline(parent, :anchor, target, type: :link, target: target)
60
+ return create_block(parent, :paragraph, link.convert, {}, content_model: :raw)
61
+ end
62
+
63
+ 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), {})
66
+ end
67
+
68
+ begin
69
+ diagram_text = read(path)
70
+ rescue => e # rubocop:disable RescueStandardError
71
+ logger.error "Failed to read #{diagram_type} file: #{path}. #{e}."
72
+ return create_block(parent, 'paragraph', unresolved_block_macro_message(diagram_type, path), {})
73
+ end
74
+ KrokiProcessor.process(self, parent, attrs, diagram_type, diagram_text, @logger)
75
+ end
76
+
77
+ protected
78
+
79
+ attr_reader :logger
80
+
81
+ def resolve_target_path(target)
82
+ target
83
+ end
84
+
85
+ def read_allowed?(_target)
86
+ true
37
87
  end
38
88
 
39
89
  def read(target)
@@ -44,32 +94,38 @@ module AsciidoctorExtensions
44
94
  File.open(target, &:read)
45
95
  end
46
96
  end
97
+
98
+ def unresolved_block_macro_message(name, target)
99
+ "Unresolved block macro - #{name}::#{target}[]"
100
+ end
47
101
  end
48
102
 
49
103
  # Kroki API
50
104
  #
51
105
  module Kroki
52
106
  SUPPORTED_DIAGRAM_NAMES = %w[
53
- plantuml
54
- ditaa
55
- graphviz
56
- blockdiag
57
- seqdiag
58
107
  actdiag
59
- nwdiag
60
- packetdiag
61
- rackdiag
108
+ blockdiag
109
+ bpmn
110
+ bytefield
62
111
  c4plantuml
112
+ ditaa
63
113
  erd
114
+ excalidraw
115
+ graphviz
64
116
  mermaid
65
117
  nomnoml
118
+ nwdiag
119
+ packetdiag
120
+ pikchr
121
+ plantuml
122
+ rackdiag
123
+ seqdiag
66
124
  svgbob
67
125
  umlet
68
126
  vega
69
127
  vegalite
70
128
  wavedrom
71
- bytefield
72
- bpmn
73
129
  ].freeze
74
130
  end
75
131
 
@@ -79,9 +135,9 @@ module AsciidoctorExtensions
79
135
  TEXT_FORMATS = %w[txt atxt utxt].freeze
80
136
 
81
137
  class << self
82
- def process(processor, parent, attrs, diagram_type, diagram_text)
138
+ def process(processor, parent, attrs, diagram_type, diagram_text, logger)
83
139
  doc = parent.document
84
- diagram_text = prepend_plantuml_config(diagram_text, diagram_type, doc)
140
+ diagram_text = prepend_plantuml_config(diagram_text, diagram_type, doc, logger)
85
141
  # If "subs" attribute is specified, substitute accordingly.
86
142
  # Be careful not to specify "specialcharacters" or your diagram code won't be valid anymore!
87
143
  if (subs = attrs['subs'])
@@ -95,7 +151,7 @@ module AsciidoctorExtensions
95
151
  attrs['role'] = get_role(format, role)
96
152
  attrs['format'] = format
97
153
  kroki_diagram = KrokiDiagram.new(diagram_type, format, diagram_text)
98
- kroki_client = KrokiClient.new(server_url(doc), http_method(doc), KrokiHttpClient)
154
+ kroki_client = KrokiClient.new(server_url(doc), http_method(doc), KrokiHttpClient, logger, max_uri_length(doc))
99
155
  if TEXT_FORMATS.include?(format)
100
156
  text_content = kroki_client.text_content(kroki_diagram)
101
157
  block = processor.create_block(parent, 'literal', text_content, attrs)
@@ -111,12 +167,17 @@ module AsciidoctorExtensions
111
167
 
112
168
  private
113
169
 
114
- def prepend_plantuml_config(diagram_text, diagram_type, doc)
115
- if diagram_type == :plantuml && doc.attr?('kroki-plantuml-include')
116
- # TODO: this behaves different than the JS version
117
- # The file should be added by !include #{plantuml_include}" once we have a preprocessor for ruby
118
- config = File.read(doc.attr('kroki-plantuml-include'))
119
- diagram_text = config + '\n' + diagram_text
170
+ def prepend_plantuml_config(diagram_text, diagram_type, doc, logger)
171
+ if diagram_type == :plantuml && doc.safe < ::Asciidoctor::SafeMode::SECURE && doc.attr?('kroki-plantuml-include')
172
+ # REMIND: this behaves different than the JS version
173
+ # Once we have a preprocessor for Ruby, the value should be added in the diagram source as "!include #{plantuml_include}"
174
+ plantuml_include_path = doc.normalize_system_path(doc.attr('kroki-plantuml-include'))
175
+ if ::File.readable? plantuml_include_path
176
+ config = File.read(plantuml_include_path)
177
+ diagram_text = config + "\n" + diagram_text
178
+ else
179
+ logger.warn "Unable to read plantuml-include. File not found or not readable: #{plantuml_include_path}."
180
+ end
120
181
  end
121
182
  diagram_text
122
183
  end
@@ -156,7 +217,7 @@ module AsciidoctorExtensions
156
217
  end
157
218
 
158
219
  def create_image_src(doc, kroki_diagram, kroki_client)
159
- if doc.attr('kroki-fetch-diagram')
220
+ if doc.attr('kroki-fetch-diagram') && doc.safe < ::Asciidoctor::SafeMode::SECURE
160
221
  kroki_diagram.save(output_dir_path(doc), kroki_client)
161
222
  else
162
223
  kroki_diagram.get_diagram_uri(server_url(doc))
@@ -171,20 +232,20 @@ module AsciidoctorExtensions
171
232
  doc.attr('kroki-http-method', 'adaptive').downcase
172
233
  end
173
234
 
235
+ def max_uri_length(doc)
236
+ doc.attr('kroki-max-uri-length', '4000').to_i
237
+ end
238
+
174
239
  def output_dir_path(doc)
175
- images_output_dir = doc.attr('imagesoutdir')
176
- out_dir = doc.attr('outdir')
177
- to_dir = doc.attr('to_dir')
178
- base_dir = doc.base_dir
179
240
  images_dir = doc.attr('imagesdir', '')
180
- if images_output_dir
241
+ if (images_output_dir = doc.attr('imagesoutdir'))
181
242
  images_output_dir
182
- elsif out_dir
243
+ elsif (out_dir = doc.attr('outdir'))
183
244
  File.join(out_dir, images_dir)
184
- elsif to_dir
245
+ elsif (to_dir = doc.attr('to_dir'))
185
246
  File.join(to_dir, images_dir)
186
247
  else
187
- File.join(base_dir, images_dir)
248
+ File.join(doc.base_dir, images_dir)
188
249
  end
189
250
  end
190
251
  end
@@ -258,18 +319,19 @@ module AsciidoctorExtensions
258
319
  class KrokiClient
259
320
  attr_reader :server_url
260
321
  attr_reader :method
322
+ attr_reader :max_uri_length
261
323
 
262
324
  SUPPORTED_HTTP_METHODS = %w[get post adaptive].freeze
263
325
 
264
- def initialize(server_url, http_method, http_client)
326
+ def initialize(server_url, http_method, http_client, logger = ::Asciidoctor::LoggerManager.logger, max_uri_length = 4000)
265
327
  @server_url = server_url
266
- @max_uri_length = 4096
328
+ @max_uri_length = max_uri_length
267
329
  @http_client = http_client
268
330
  method = (http_method || 'adaptive').downcase
269
331
  if SUPPORTED_HTTP_METHODS.include?(method)
270
332
  @method = method
271
333
  else
272
- puts "Invalid value '#{method}' for kroki-http-method attribute. The value must be either: 'get', 'post' or 'adaptive'. Proceeding using: 'adaptive'."
334
+ logger.warn "Invalid value '#{method}' for kroki-http-method attribute. The value must be either: 'get', 'post' or 'adaptive'. Proceeding using: 'adaptive'."
273
335
  @method = 'adaptive'
274
336
  end
275
337
  end
@@ -285,7 +347,7 @@ module AsciidoctorExtensions
285
347
  if @method == 'adaptive' || @method == 'get'
286
348
  uri = kroki_diagram.get_diagram_uri(server_url)
287
349
  if uri.length > @max_uri_length
288
- # The request URI is longer than 4096.
350
+ # The request URI is longer than the max URI length.
289
351
  if @method == 'get'
290
352
  # The request might be rejected by the server with a 414 Request-URI Too Large.
291
353
  # Consider using the attribute kroki-http-method with the value 'adaptive'.
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec_helper'
4
+ require 'asciidoctor'
5
+ require_relative '../lib/asciidoctor/extensions/asciidoctor_kroki'
6
+ require_relative '../lib/asciidoctor/extensions/asciidoctor_kroki/extension'
7
+
8
+ describe ::AsciidoctorExtensions::KrokiBlockMacroProcessor do
9
+ context 'convert to html5' do
10
+ it 'should catch exception if target is not readable' do
11
+ input = <<~'ADOC'
12
+ plantuml::spec/fixtures/missing.puml[svg,role=sequence]
13
+ ADOC
14
+ output = Asciidoctor.convert(input, standalone: false)
15
+ (expect output).to eql %(<div class="paragraph">
16
+ <p>Unresolved block macro - plantuml::spec/fixtures/missing.puml[]</p>
17
+ </div>)
18
+ end
19
+ end
20
+ context 'using a custom block macro' do
21
+ it 'should disallow read' do
22
+ # noinspection RubyClassModuleNamingConvention
23
+ class DisallowReadKrokiBlockMacroProcessor < ::AsciidoctorExtensions::KrokiBlockMacroProcessor
24
+ def read_allowed?(_target)
25
+ false
26
+ end
27
+ end
28
+ registry = Asciidoctor::Extensions.create do
29
+ block_macro DisallowReadKrokiBlockMacroProcessor, 'plantuml'
30
+ end
31
+ input = <<~'ADOC'
32
+ plantuml::spec/fixtures/alice.puml[svg,role=sequence]
33
+ ADOC
34
+ output = Asciidoctor.convert(input, standalone: false, extension_registry: registry)
35
+ (expect output).to eql %(<div class="paragraph">
36
+ <p><a href="spec/fixtures/alice.puml">spec/fixtures/alice.puml</a></p>
37
+ </div>)
38
+ end
39
+ it 'should allow read if target is not a URI' do
40
+ # noinspection RubyClassModuleNamingConvention
41
+ class DisallowUriReadKrokiBlockMacroProcessor < ::AsciidoctorExtensions::KrokiBlockMacroProcessor
42
+ def read_allowed?(target)
43
+ return false if ::Asciidoctor::Helpers.uriish?(target)
44
+
45
+ true
46
+ end
47
+ end
48
+ registry = Asciidoctor::Extensions.create do
49
+ block_macro DisallowUriReadKrokiBlockMacroProcessor, 'plantuml'
50
+ end
51
+ input = <<~'ADOC'
52
+ plantuml::https://domain.org/alice.puml[svg,role=sequence]
53
+
54
+ plantuml::file://path/to/alice.puml[svg,role=sequence]
55
+
56
+ plantuml::spec/fixtures/alice.puml[svg,role=sequence]
57
+ ADOC
58
+ output = Asciidoctor.convert(input, standalone: false, extension_registry: registry)
59
+ (expect output).to eql %(<div class="paragraph">
60
+ <p><a href="https://domain.org/alice.puml">https://domain.org/alice.puml</a></p>
61
+ </div>
62
+ <div class="paragraph">
63
+ <p><a href="file://path/to/alice.puml">file://path/to/alice.puml</a></p>
64
+ </div>
65
+ <div class="imageblock sequence kroki-format-svg kroki">
66
+ <div class="content">
67
+ <img src="https://kroki.io/plantuml/svg/eNpLzMlMTlXQtVNIyk-yUshIzcnJ5wIAQ-AGVQ==" alt="Diagram">
68
+ </div>
69
+ </div>)
70
+ end
71
+ it 'should override the resolve target method' do
72
+ # noinspection RubyClassModuleNamingConvention
73
+ class FixtureResolveTargetKrokiBlockMacroProcessor < ::AsciidoctorExtensions::KrokiBlockMacroProcessor
74
+ def resolve_target_path(target)
75
+ "spec/fixtures/#{target}"
76
+ end
77
+ end
78
+ registry = Asciidoctor::Extensions.create do
79
+ block_macro FixtureResolveTargetKrokiBlockMacroProcessor, 'plantuml'
80
+ end
81
+ input = <<~'ADOC'
82
+ plantuml::alice.puml[svg,role=sequence]
83
+ ADOC
84
+ output = Asciidoctor.convert(input, standalone: false, extension_registry: registry)
85
+ (expect output).to eql %(<div class="imageblock sequence kroki-format-svg kroki">
86
+ <div class="content">
87
+ <img src="https://kroki.io/plantuml/svg/eNpLzMlMTlXQtVNIyk-yUshIzcnJ5wIAQ-AGVQ==" alt="Diagram">
88
+ </div>
89
+ </div>)
90
+ end
91
+ it 'should display unresolved block macro message when the traget cannot be resolved' do
92
+ # noinspection RubyClassModuleNamingConvention
93
+ class UnresolvedTargetKrokiBlockMacroProcessor < ::AsciidoctorExtensions::KrokiBlockMacroProcessor
94
+ def resolve_target_path(_target)
95
+ nil
96
+ end
97
+ end
98
+ registry = Asciidoctor::Extensions.create do
99
+ block_macro UnresolvedTargetKrokiBlockMacroProcessor, 'plantuml'
100
+ end
101
+ input = <<~'ADOC'
102
+ plantuml::alice.puml[svg,role=sequence]
103
+ ADOC
104
+ output = Asciidoctor.convert(input, standalone: false, extension_registry: registry)
105
+ (expect output).to eql %(<div class="paragraph">
106
+ <p>Unresolved block macro - plantuml::[]</p>
107
+ </div>)
108
+ end
109
+ it 'should override the unresolved block macro message' do
110
+ # noinspection RubyClassModuleNamingConvention
111
+ class CustomUnresolvedTargetMessageKrokiBlockMacroProcessor < ::AsciidoctorExtensions::KrokiBlockMacroProcessor
112
+ def unresolved_block_macro_message(name, target)
113
+ "*[ERROR: #{name}::#{target}[] - unresolved block macro]*"
114
+ end
115
+ end
116
+ registry = Asciidoctor::Extensions.create do
117
+ block_macro CustomUnresolvedTargetMessageKrokiBlockMacroProcessor, 'plantuml'
118
+ end
119
+ input = <<~'ADOC'
120
+ plantuml::spec/fixtures/missing.puml[svg,role=sequence]
121
+ ADOC
122
+ output = Asciidoctor.convert(input, standalone: false, extension_registry: registry)
123
+ (expect output).to eql %(<div class="paragraph">
124
+ <p><strong>[ERROR: plantuml::spec/fixtures/missing.puml[] - unresolved block macro]</strong></p>
125
+ </div>)
126
+ end
127
+ end
128
+ end
@@ -20,4 +20,72 @@ describe ::AsciidoctorExtensions::KrokiClient do
20
20
  kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'get', kroki_http_client)
21
21
  expect(kroki_client.method).to eq('get')
22
22
  end
23
+ it 'should use 4000 as the default max URI length' do
24
+ kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient
25
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'get', kroki_http_client)
26
+ expect(kroki_client.max_uri_length).to eq(4000)
27
+ end
28
+ it 'should use a custom value as max URI length' do
29
+ kroki_http_client = ::AsciidoctorExtensions::KrokiHttpClient
30
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'get', kroki_http_client, nil, 8000)
31
+ expect(kroki_client.max_uri_length).to eq(8000)
32
+ end
33
+ it 'should get an image with POST request if the URI length is greater than the value configured' do
34
+ kroki_http_client = Class.new do
35
+ class << self
36
+ def get(uri, _)
37
+ "GET #{uri}"
38
+ end
39
+
40
+ def post(uri, data, _)
41
+ "POST #{uri} - #{data}"
42
+ end
43
+ end
44
+ end
45
+ kroki_diagram = Class.new do
46
+ attr_reader :type, :text, :format
47
+
48
+ def initialize(type, format, text)
49
+ @text = text
50
+ @type = type
51
+ @format = format
52
+ end
53
+
54
+ def get_diagram_uri(_)
55
+ 'diagram-uri'
56
+ end
57
+ end.new('type', 'format', 'text')
58
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'adaptive', kroki_http_client, nil, 10)
59
+ result = kroki_client.get_image(kroki_diagram, 'utf8')
60
+ expect(result).to eq('POST http://localhost:8000/type/format - text')
61
+ end
62
+ it 'should get an image with GET request if the URI length is lower or equals than the value configured' do
63
+ kroki_http_client = Class.new do
64
+ class << self
65
+ def get(uri, _)
66
+ "GET #{uri}"
67
+ end
68
+
69
+ def post(uri, data, _)
70
+ "POST #{uri} - #{data}"
71
+ end
72
+ end
73
+ end
74
+ kroki_diagram = Class.new do
75
+ attr_reader :type, :text, :format
76
+
77
+ def initialize(type, format, text)
78
+ @text = text
79
+ @type = type
80
+ @format = format
81
+ end
82
+
83
+ def get_diagram_uri(_)
84
+ 'diagram-uri'
85
+ end
86
+ end.new('type', 'format', 'text')
87
+ kroki_client = ::AsciidoctorExtensions::KrokiClient.new('http://localhost:8000', 'adaptive', kroki_http_client, nil, 11)
88
+ result = kroki_client.get_image(kroki_diagram, 'utf8')
89
+ expect(result).to eq('GET diagram-uri')
90
+ end
23
91
  end
@@ -34,17 +34,59 @@ describe ::AsciidoctorExtensions::KrokiBlockProcessor do
34
34
  </div>
35
35
  </div>)
36
36
  end
37
- it 'should include the plantuml-include file' do
37
+ it 'should include the plantuml-include file when safe mode is safe' do
38
38
  input = <<~'ADOC'
39
39
  [plantuml]
40
40
  ....
41
41
  alice -> bob: hello
42
42
  ....
43
43
  ADOC
44
- output = Asciidoctor.convert(input, attributes: { 'env-idea' => '', 'kroki-plantuml-include' => 'spec/fixtures/config.puml' }, standalone: false)
44
+ output = Asciidoctor.convert(input, attributes: { 'env-idea' => '', 'kroki-plantuml-include' => 'spec/fixtures/config.puml' }, standalone: false, safe: :safe)
45
45
  (expect output).to eql %(<div class="imageblock kroki">
46
46
  <div class="content">
47
- <img src="https://kroki.io/plantuml/png/eNorzs7MK0gsSsxVyM3Py0_OKMrPTVUoKSpN5YrJS8zJTE5V0LVTSMpPslLISM3JyQcArVsRHA==" alt="Diagram">
47
+ <img src="https://kroki.io/plantuml/png/eNorzs7MK0gsSsxVyM3Py0_OKMrPTVUoKSpN5eJKzMlMTlXQtVNIyk-yUshIzcnJBwCT9xBc" alt="Diagram">
48
+ </div>
49
+ </div>)
50
+ end
51
+ it 'should normalize plantuml-include path when safe mode is safe' do
52
+ input = <<~'ADOC'
53
+ [plantuml]
54
+ ....
55
+ alice -> bob: hello
56
+ ....
57
+ ADOC
58
+ output = Asciidoctor.convert(input, attributes: { 'env-idea' => '', 'kroki-plantuml-include' => '../../../spec/fixtures/config.puml' }, standalone: false, safe: :safe)
59
+ (expect output).to eql %(<div class="imageblock kroki">
60
+ <div class="content">
61
+ <img src="https://kroki.io/plantuml/png/eNorzs7MK0gsSsxVyM3Py0_OKMrPTVUoKSpN5eJKzMlMTlXQtVNIyk-yUshIzcnJBwCT9xBc" alt="Diagram">
62
+ </div>
63
+ </div>)
64
+ end
65
+ it 'should not include file which reside outside of the parent directory of the source when safe mode is safe' do
66
+ input = <<~'ADOC'
67
+ [plantuml]
68
+ ....
69
+ alice -> bob: hello
70
+ ....
71
+ ADOC
72
+ output = Asciidoctor.convert(input, attributes: { 'env-idea' => '', 'kroki-plantuml-include' => '/etc/passwd' }, standalone: false, safe: :safe)
73
+ (expect output).to eql %(<div class="imageblock kroki">
74
+ <div class="content">
75
+ <img src="https://kroki.io/plantuml/png/eNpLzMlMTlXQtVNIyk-yUshIzcnJBwA9iwZL" alt="Diagram">
76
+ </div>
77
+ </div>)
78
+ end
79
+ it 'should not include file when safe mode is secure' do
80
+ input = <<~'ADOC'
81
+ [plantuml]
82
+ ....
83
+ alice -> bob: hello
84
+ ....
85
+ ADOC
86
+ output = Asciidoctor.convert(input, attributes: { 'env-idea' => '', 'kroki-plantuml-include' => 'spec/fixtures/config.puml' }, standalone: false, safe: :secure)
87
+ (expect output).to eql %(<div class="imageblock kroki">
88
+ <div class="content">
89
+ <img src="https://kroki.io/plantuml/png/eNpLzMlMTlXQtVNIyk-yUshIzcnJBwA9iwZL" alt="Diagram">
48
90
  </div>
49
91
  </div>)
50
92
  end
@@ -54,11 +96,24 @@ describe ::AsciidoctorExtensions::KrokiBlockProcessor do
54
96
 
55
97
  plantuml::spec/fixtures/alice.puml[svg,role=sequence]
56
98
  ADOC
57
- output = Asciidoctor.convert(input, attributes: { 'kroki-fetch-diagram' => '' }, standalone: false)
99
+ output = Asciidoctor.convert(input, attributes: { 'kroki-fetch-diagram' => '' }, standalone: false, safe: :safe)
58
100
  (expect output).to eql %(<div class="imageblock sequence kroki-format-svg kroki">
59
101
  <div class="content">
60
102
  <img src=".asciidoctor/kroki/diag-f6acdc206506b6ca7badd3fe722f252af992871426e580c8361ff4d47c2c7d9b.svg" alt="Diagram">
61
103
  </div>
104
+ </div>)
105
+ end
106
+ it 'should not fetch diagram when safe mode is secure' do
107
+ input = <<~'ADOC'
108
+ :imagesdir: .asciidoctor/kroki
109
+
110
+ plantuml::spec/fixtures/alice.puml[svg,role=sequence]
111
+ ADOC
112
+ output = Asciidoctor.convert(input, attributes: { 'kroki-fetch-diagram' => '' }, standalone: false)
113
+ (expect output).to eql %(<div class="imageblock sequence kroki-format-svg kroki">
114
+ <div class="content">
115
+ <img src="https://kroki.io/plantuml/svg/eNpLzMlMTlXQtVNIyk-yUshIzcnJ5wIAQ-AGVQ==" alt="Diagram">
116
+ </div>
62
117
  </div>)
63
118
  end
64
119
  it 'should create PNG diagram in imagesdir if kroki-fetch-diagram is set' do
@@ -67,7 +122,7 @@ describe ::AsciidoctorExtensions::KrokiBlockProcessor do
67
122
 
68
123
  plantuml::spec/fixtures/alice.puml[png,role=sequence]
69
124
  ADOC
70
- output = Asciidoctor.convert(input, attributes: { 'kroki-fetch-diagram' => '' }, standalone: false)
125
+ output = Asciidoctor.convert(input, attributes: { 'kroki-fetch-diagram' => '' }, standalone: false, safe: :safe)
71
126
  (expect output).to eql %(<div class="imageblock sequence kroki-format-png kroki">
72
127
  <div class="content">
73
128
  <img src=".asciidoctor/kroki/diag-d4f314b2d4e75cc08aa4f8c2c944f7bf78321895d8ec5f665b42476d4e67e610.png" alt="Diagram">
@@ -75,12 +130,23 @@ describe ::AsciidoctorExtensions::KrokiBlockProcessor do
75
130
  </div>)
76
131
  end
77
132
  end
133
+ context 'instantiate' do
134
+ it 'should instantiate block processor without warning' do
135
+ original_stderr = $stderr
136
+ $stderr = StringIO.new
137
+ ::AsciidoctorExtensions::KrokiBlockProcessor.new 'plantuml'.to_sym, {}
138
+ output = $stderr.string
139
+ (expect output).to eql ''
140
+ ensure
141
+ $stderr = original_stderr
142
+ end
143
+ end
78
144
  end
79
145
 
80
146
  describe ::AsciidoctorExtensions::Kroki do
81
147
  it 'should return the list of supported diagrams' do
82
148
  diagram_names = ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES
83
- expect(diagram_names).to include('vegalite', 'plantuml', 'bytefield', 'bpmn')
149
+ expect(diagram_names).to include('vegalite', 'plantuml', 'bytefield', 'bpmn', 'excalidraw', 'wavedrom', 'pikchr')
84
150
  end
85
151
  it 'should register the extension for the list of supported diagrams' do
86
152
  doc = Asciidoctor::Document.new
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.2.0
4
+ version: 0.5.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: 2020-10-19 00:00:00.000000000 Z
11
+ date: 2021-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
- - !ruby/object:Gem::Dependency
28
- name: asciidoctor-pdf
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '='
32
- - !ruby/object:Gem::Version
33
- version: 1.5.3
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - '='
39
- - !ruby/object:Gem::Version
40
- version: 1.5.3
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: rake
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -99,6 +85,7 @@ files:
99
85
  - lib/asciidoctor/extensions/asciidoctor_kroki.rb
100
86
  - lib/asciidoctor/extensions/asciidoctor_kroki/extension.rb
101
87
  - spec/.rubocop.yml
88
+ - spec/asciidoctor_kroki_block_macro_spec.rb
102
89
  - spec/asciidoctor_kroki_client_spec.rb
103
90
  - spec/asciidoctor_kroki_diagram_spec.rb
104
91
  - spec/asciidoctor_kroki_spec.rb
@@ -130,12 +117,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
117
  - !ruby/object:Gem::Version
131
118
  version: '0'
132
119
  requirements: []
133
- rubygems_version: 3.0.3
120
+ rubygems_version: 3.1.6
134
121
  signing_key:
135
122
  specification_version: 4
136
123
  summary: Asciidoctor extension to convert diagrams to images using Kroki
137
124
  test_files:
138
125
  - spec/.rubocop.yml
126
+ - spec/asciidoctor_kroki_block_macro_spec.rb
139
127
  - spec/asciidoctor_kroki_client_spec.rb
140
128
  - spec/asciidoctor_kroki_diagram_spec.rb
141
129
  - spec/asciidoctor_kroki_spec.rb