asciidoctor-kroki 0.3.0 → 0.4.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: c68a706bac6918c95daef5ada0de0d6a8471cbd69cc83ced875119ca69b90f58
4
- data.tar.gz: c2683ddf3c70e743faff32a73442ef651fd17145191148e4a5930ac7d16852f9
3
+ metadata.gz: dfa0c461bdb74571b618747d791e059125dc09a5e67dd6886861101fe972237f
4
+ data.tar.gz: d882ff8e33c787b3a1578eb7d11b590411e18f594eaec188d7f06ffc182a3b11
5
5
  SHA512:
6
- metadata.gz: 45ea1d0252ebfab9fc9dfba56b13a3497ddf1e5ca58cb05777c941829ec2316f0f194a87bef490483c800d43cd7cf0e008804cb4f92ad4955cc864203ad26dfb
7
- data.tar.gz: 3fec5d036175f848b0fa26df6c47439ee2f61a776393c097ecb0e79e0f407939e99df233bb1461360feaf4aae4224377aadff7bbc9d93ffa6fad6af62f7fc40e
6
+ metadata.gz: f72b7293f3fb8c6d37b456c39d4e2691c0b65e1cb908d5f3f29d23466f0c51135b9977dd0977a2ccac7adb667b4fc5071a4a5fc59bed6a3304154bddc8efda3d
7
+ data.tar.gz: 1e93fbf9df1cab9282f7743f76331ea6caddfdce150fff36fb7aa7222d561d089c31101ec0f16a939f5aa2c0c7dd5a09206059700974b76ae6fadcfc0150acd3
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,13 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- asciidoctor-kroki (0.3.0)
4
+ asciidoctor-kroki (0.4.0)
5
5
  asciidoctor (~> 2.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- asciidoctor (2.0.10)
10
+ asciidoctor (2.0.11)
11
11
  ast (2.4.1)
12
12
  diff-lcs (1.3)
13
13
  jaro_winkler (1.5.4)
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'asciidoctor-kroki'
5
- s.version = '0.3.0'
5
+ s.version = '0.4.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
 
@@ -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
+ # @param logger [Logger] a logger used to log warning and errors (optional)
21
+ #
22
+ def initialize(name = nil, config = {}, logger: ::Asciidoctor::LoggerManager.logger)
23
+ super(name, config)
24
+ @logger = logger
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
+ # @param logger [Logger] a logger used to log warning and errors (optional)
48
+ #
49
+ def initialize(name = nil, config = {}, logger: ::Asciidoctor::LoggerManager.logger)
50
+ super(name, config)
51
+ @logger = logger
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,6 +94,10 @@ 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
@@ -70,7 +124,7 @@ module AsciidoctorExtensions
70
124
  umlet
71
125
  vega
72
126
  vegalite
73
- wavedrow
127
+ wavedrom
74
128
  ].freeze
75
129
  end
76
130
 
@@ -80,9 +134,9 @@ module AsciidoctorExtensions
80
134
  TEXT_FORMATS = %w[txt atxt utxt].freeze
81
135
 
82
136
  class << self
83
- def process(processor, parent, attrs, diagram_type, diagram_text)
137
+ def process(processor, parent, attrs, diagram_type, diagram_text, logger)
84
138
  doc = parent.document
85
- diagram_text = prepend_plantuml_config(diagram_text, diagram_type, doc)
139
+ diagram_text = prepend_plantuml_config(diagram_text, diagram_type, doc, logger)
86
140
  # If "subs" attribute is specified, substitute accordingly.
87
141
  # Be careful not to specify "specialcharacters" or your diagram code won't be valid anymore!
88
142
  if (subs = attrs['subs'])
@@ -96,7 +150,7 @@ module AsciidoctorExtensions
96
150
  attrs['role'] = get_role(format, role)
97
151
  attrs['format'] = format
98
152
  kroki_diagram = KrokiDiagram.new(diagram_type, format, diagram_text)
99
- kroki_client = KrokiClient.new(server_url(doc), http_method(doc), KrokiHttpClient)
153
+ kroki_client = KrokiClient.new(server_url(doc), http_method(doc), KrokiHttpClient, logger, max_uri_length(doc))
100
154
  if TEXT_FORMATS.include?(format)
101
155
  text_content = kroki_client.text_content(kroki_diagram)
102
156
  block = processor.create_block(parent, 'literal', text_content, attrs)
@@ -112,12 +166,17 @@ module AsciidoctorExtensions
112
166
 
113
167
  private
114
168
 
115
- def prepend_plantuml_config(diagram_text, diagram_type, doc)
116
- if diagram_type == :plantuml && doc.attr?('kroki-plantuml-include')
117
- # TODO: this behaves different than the JS version
118
- # The file should be added by !include #{plantuml_include}" once we have a preprocessor for ruby
119
- config = File.read(doc.attr('kroki-plantuml-include'))
120
- diagram_text = config + '\n' + diagram_text
169
+ def prepend_plantuml_config(diagram_text, diagram_type, doc, logger)
170
+ if diagram_type == :plantuml && doc.safe < ::Asciidoctor::SafeMode::SECURE && doc.attr?('kroki-plantuml-include')
171
+ # REMIND: this behaves different than the JS version
172
+ # Once we have a preprocessor for Ruby, the value should be added in the diagram source as "!include #{plantuml_include}"
173
+ plantuml_include_path = doc.normalize_system_path(doc.attr('kroki-plantuml-include'))
174
+ if ::File.readable? plantuml_include_path
175
+ config = File.read(plantuml_include_path)
176
+ diagram_text = config + "\n" + diagram_text
177
+ else
178
+ logger.warn "Unable to read plantuml-include. File not found or not readable: #{plantuml_include_path}."
179
+ end
121
180
  end
122
181
  diagram_text
123
182
  end
@@ -157,7 +216,7 @@ module AsciidoctorExtensions
157
216
  end
158
217
 
159
218
  def create_image_src(doc, kroki_diagram, kroki_client)
160
- if doc.attr('kroki-fetch-diagram')
219
+ if doc.attr('kroki-fetch-diagram') && doc.safe < ::Asciidoctor::SafeMode::SECURE
161
220
  kroki_diagram.save(output_dir_path(doc), kroki_client)
162
221
  else
163
222
  kroki_diagram.get_diagram_uri(server_url(doc))
@@ -172,20 +231,20 @@ module AsciidoctorExtensions
172
231
  doc.attr('kroki-http-method', 'adaptive').downcase
173
232
  end
174
233
 
234
+ def max_uri_length(doc)
235
+ doc.attr('kroki-max-uri-length', '4000').to_i
236
+ end
237
+
175
238
  def output_dir_path(doc)
176
- images_output_dir = doc.attr('imagesoutdir')
177
- out_dir = doc.attr('outdir')
178
- to_dir = doc.attr('to_dir')
179
- base_dir = doc.base_dir
180
239
  images_dir = doc.attr('imagesdir', '')
181
- if images_output_dir
240
+ if (images_output_dir = doc.attr('imagesoutdir'))
182
241
  images_output_dir
183
- elsif out_dir
242
+ elsif (out_dir = doc.attr('outdir'))
184
243
  File.join(out_dir, images_dir)
185
- elsif to_dir
244
+ elsif (to_dir = doc.attr('to_dir'))
186
245
  File.join(to_dir, images_dir)
187
246
  else
188
- File.join(base_dir, images_dir)
247
+ File.join(doc.base_dir, images_dir)
189
248
  end
190
249
  end
191
250
  end
@@ -259,18 +318,19 @@ module AsciidoctorExtensions
259
318
  class KrokiClient
260
319
  attr_reader :server_url
261
320
  attr_reader :method
321
+ attr_reader :max_uri_length
262
322
 
263
323
  SUPPORTED_HTTP_METHODS = %w[get post adaptive].freeze
264
324
 
265
- def initialize(server_url, http_method, http_client)
325
+ def initialize(server_url, http_method, http_client, logger = ::Asciidoctor::LoggerManager.logger, max_uri_length = 4000)
266
326
  @server_url = server_url
267
- @max_uri_length = 4096
327
+ @max_uri_length = max_uri_length
268
328
  @http_client = http_client
269
329
  method = (http_method || 'adaptive').downcase
270
330
  if SUPPORTED_HTTP_METHODS.include?(method)
271
331
  @method = method
272
332
  else
273
- puts "Invalid value '#{method}' for kroki-http-method attribute. The value must be either: 'get', 'post' or 'adaptive'. Proceeding using: 'adaptive'."
333
+ logger.warn "Invalid value '#{method}' for kroki-http-method attribute. The value must be either: 'get', 'post' or 'adaptive'. Proceeding using: 'adaptive'."
274
334
  @method = 'adaptive'
275
335
  end
276
336
  end
@@ -286,7 +346,7 @@ module AsciidoctorExtensions
286
346
  if @method == 'adaptive' || @method == 'get'
287
347
  uri = kroki_diagram.get_diagram_uri(server_url)
288
348
  if uri.length > @max_uri_length
289
- # The request URI is longer than 4096.
349
+ # The request URI is longer than the max URI length.
290
350
  if @method == 'get'
291
351
  # The request might be rejected by the server with a 414 Request-URI Too Large.
292
352
  # 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">
@@ -80,7 +135,7 @@ end
80
135
  describe ::AsciidoctorExtensions::Kroki do
81
136
  it 'should return the list of supported diagrams' do
82
137
  diagram_names = ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES
83
- expect(diagram_names).to include('vegalite', 'plantuml', 'bytefield', 'bpmn', 'excalidraw')
138
+ expect(diagram_names).to include('vegalite', 'plantuml', 'bytefield', 'bpmn', 'excalidraw', 'wavedrom')
84
139
  end
85
140
  it 'should register the extension for the list of supported diagrams' do
86
141
  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.3.0
4
+ version: 0.4.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-01-12 00:00:00.000000000 Z
11
+ date: 2021-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -85,6 +85,7 @@ files:
85
85
  - lib/asciidoctor/extensions/asciidoctor_kroki.rb
86
86
  - lib/asciidoctor/extensions/asciidoctor_kroki/extension.rb
87
87
  - spec/.rubocop.yml
88
+ - spec/asciidoctor_kroki_block_macro_spec.rb
88
89
  - spec/asciidoctor_kroki_client_spec.rb
89
90
  - spec/asciidoctor_kroki_diagram_spec.rb
90
91
  - spec/asciidoctor_kroki_spec.rb
@@ -122,6 +123,7 @@ specification_version: 4
122
123
  summary: Asciidoctor extension to convert diagrams to images using Kroki
123
124
  test_files:
124
125
  - spec/.rubocop.yml
126
+ - spec/asciidoctor_kroki_block_macro_spec.rb
125
127
  - spec/asciidoctor_kroki_client_spec.rb
126
128
  - spec/asciidoctor_kroki_diagram_spec.rb
127
129
  - spec/asciidoctor_kroki_spec.rb