asciidoctor-plantuml 0.0.15 → 0.1.1

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: 7673d42a2b0bcc381cb0111511bfc05584ed0c509dfad8dcf9b20919b9d8b689
4
- data.tar.gz: 2a8c98b8a3adfc09e57a7928e9f23a86230072da14ca9a9593d627401f40d194
3
+ metadata.gz: fa9d42baca46ef240d1621640dce548f96a46e4e535a6405cace400e2495f097
4
+ data.tar.gz: b7320f06086d5230ceb3507945971f48efe988edfd159ebde0cc1c5609bc86f6
5
5
  SHA512:
6
- metadata.gz: 9ed82c582714d60f1a0cf57d5bbb070250dc07744a7545b28912d2e4e97f13ceff292d3d528df7f23ea683e4bfbd1cd6ce5c2500f1b8fb2b274429395fede02c
7
- data.tar.gz: 78e840faff576976ecdf0d1584d0e9b86d07a8afed74c7248f210d7bd306a25c1c67c1bb41165d2e54b559d02f122d0cc8c8d960c989b0a3a0fc057f32e4d600
6
+ metadata.gz: e0f9dc73e4f6f116b1321d2d25a23a268d8158777abeb2c3984c5ce642dd1aecbe2febeb602d9d8e0fb038cb310fb934f460300996170e2e83d81a57fc159588
7
+ data.tar.gz: b9aea5f39cb2c27e48b1239518a9d8a63b7938cc81899c3454782a6afe235a0597817525bdfe125441e09f03dcc4b6abd276fc1509f5b8aa86abcf64e2287afd
@@ -6,4 +6,5 @@ require_relative 'asciidoctor_plantuml/plantuml'
6
6
 
7
7
  Asciidoctor::Extensions.register do
8
8
  block Asciidoctor::PlantUml::BlockProcessor, :plantuml
9
+ block_macro Asciidoctor::PlantUml::BlockMacroProcessor, :plantuml
9
10
  end
@@ -10,8 +10,8 @@ module Asciidoctor
10
10
  module PlantUml
11
11
  # PlantUML Configuration
12
12
  class Configuration
13
- DEFAULT_URL = ENV['PLANTUML_URL'] || ''
14
- DEFAULT_ENCODING = ENV['PLANTUML_ENCODING'] || 'legacy'
13
+ DEFAULT_URL = ENV.fetch('PLANTUML_URL', '')
14
+ DEFAULT_ENCODING = ENV.fetch('PLANTUML_ENCODING', 'legacy')
15
15
 
16
16
  attr_accessor :url, :txt_enable, :svg_enable, :png_enable, :encoding
17
17
 
@@ -78,23 +78,56 @@ module Asciidoctor
78
78
  txt_enabled? || png_enabled? || svg_enabled?
79
79
  end
80
80
 
81
- def plantuml_content_format(code, format, attrs = {})
82
- if %w[png svg txt].include?(format) &&
83
- method("#{format}_enabled?").call
84
- method("plantuml_#{format}_content").call(code, format, attrs)
81
+ def plantuml_content_format(parent, code, format, attrs = {})
82
+ content = code.read
83
+
84
+ # honor subs attributes
85
+ # e.g. replace asciidoc variables
86
+ subs = attrs['subs']
87
+ content = parent.apply_subs(content, parent.resolve_subs(subs)) if subs
88
+
89
+ # add @start... and @end... if missing
90
+ content = "@startuml\n#{content}\n@enduml" unless content =~ /^@start.*@end[a-z]*$/m
91
+
92
+ # insert global plantuml config after first line
93
+ config_path = parent.attr('plantuml-include', '', true)
94
+
95
+ unless config_path.empty?
96
+ begin
97
+ source_file = parent.document.normalize_system_path(config_path, nil, nil, recover: false)
98
+ content = insert_config_to_content(parent, source_file, content, attrs)
99
+ rescue StandardError => e
100
+ return plantuml_invalid_file(source_file, e.message, attrs)
101
+ rescue SecurityError => e
102
+ return plantuml_insecure_file(source_file, e.message, attrs)
103
+ end
104
+ end
105
+
106
+ if %w[png svg txt].include?(format) && method("#{format}_enabled?").call
107
+ method("plantuml_#{format}_content").call(content, format, attrs)
85
108
  else
86
109
  plantuml_invalid_content(format, attrs)
87
110
  end
88
111
  end
89
112
 
90
- def plantuml_content(code, attrs = {})
113
+ def plantuml_content(parent, code, attrs = {})
91
114
  format = attrs['format'] || DEFAULT_FORMAT
92
115
 
93
116
  return plantuml_disabled_content(code, attrs) unless enabled?
94
117
 
95
118
  return plantuml_server_unavailable_content(server_url, attrs) unless valid_uri?(server_url)
96
119
 
97
- plantuml_content_format(code, format, attrs)
120
+ plantuml_content_format(parent, code, format, attrs)
121
+ end
122
+
123
+ def plantuml_content_from_file(parent, target, attrs = {})
124
+ source_file = parent.document.normalize_system_path(target, nil, nil, recover: false)
125
+ content = ::File.open(source_file, mode: FILE_READ_MODE)
126
+ plantuml_content(parent, content, attrs)
127
+ rescue StandardError => e
128
+ plantuml_invalid_file(source_file, e.message, attrs)
129
+ rescue SecurityError => e
130
+ plantuml_insecure_file(source_file, e.message, attrs)
98
131
  end
99
132
 
100
133
  # Compression code used to generate PlantUML URLs. Taken directly from
@@ -113,8 +146,23 @@ module Asciidoctor
113
146
  join_paths(server_url, "#{format}/", result).to_s
114
147
  end
115
148
 
149
+ def create_plantuml_block(parent, content, attrs)
150
+ Asciidoctor::Block.new parent, :pass, {
151
+ content_model: :raw,
152
+ source: content,
153
+ subs: :default
154
+ }.merge(attrs)
155
+ end
156
+
116
157
  private
117
158
 
159
+ def insert_config_to_content(parent, config_path, content, attrs)
160
+ config = File.read(config_path, mode: FILE_READ_MODE)
161
+ subs = attrs['subs']
162
+ config = parent.apply_subs(config, parent.resolve_subs(subs)) if subs
163
+ return content.dup.insert(content.index("\n"), "\n#{config}") unless config.empty?
164
+ end
165
+
118
166
  def plantuml_txt_content(code, format, attrs = {})
119
167
  url = gen_url(code, format)
120
168
  URI(url).open do |f|
@@ -180,6 +228,16 @@ module Asciidoctor
180
228
  _plantuml_error_content(code, attrs)
181
229
  end
182
230
 
231
+ def plantuml_invalid_file(file, error, attrs = {})
232
+ error = "PlantUML Error: Could not parse \"#{file}\": #{error}"
233
+ _plantuml_error_content(error, attrs)
234
+ end
235
+
236
+ def plantuml_insecure_file(file, error, attrs = {})
237
+ error = "PlantUML Error: Could not read \"#{file}\": #{error}"
238
+ _plantuml_error_content(error, attrs)
239
+ end
240
+
183
241
  def _plantuml_error_content(error, attrs = {})
184
242
  content = '<div class="listingblock">'
185
243
  content += '<div class="content">'
@@ -246,7 +304,7 @@ module Asciidoctor
246
304
  end
247
305
 
248
306
  def expand_path(path, current, last, separator)
249
- path = path[1..-1] if path.start_with?(separator) && current.zero?
307
+ path = path[1..] if path.start_with?(separator) && current.zero?
250
308
 
251
309
  path = [path, separator] unless path.end_with?(separator) || current == last
252
310
 
@@ -263,25 +321,19 @@ module Asciidoctor
263
321
  content_model :simple
264
322
 
265
323
  def process(parent, target, attrs)
266
- lines = target.lines
267
-
268
- lines = ['@startuml'] + target.lines unless target.lines[0] =~ /@startuml/
269
-
270
- lines += ['@enduml'] unless target.lines[-1] =~ /@enduml/
271
-
272
- content = Processor.plantuml_content(lines.join("\n"), attrs)
273
-
274
- create_plantuml_block(parent, content, attrs)
324
+ content = Processor.plantuml_content(parent, target, attrs)
325
+ Processor.create_plantuml_block(parent, content, attrs)
275
326
  end
327
+ end
276
328
 
277
- private
329
+ # PlantUML BlockMacroProcessor
330
+ class BlockMacroProcessor < Asciidoctor::Extensions::BlockMacroProcessor
331
+ use_dsl
332
+ named :plantuml
278
333
 
279
- def create_plantuml_block(parent, content, attrs)
280
- Asciidoctor::Block.new parent, :pass, {
281
- content_model: :raw,
282
- source: content,
283
- subs: :default
284
- }.merge(attrs)
334
+ def process(parent, target, attrs)
335
+ content = Processor.plantuml_content_from_file(parent, target, attrs)
336
+ Processor.create_plantuml_block(parent, content, attrs)
285
337
  end
286
338
  end
287
339
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Asciidoctor
4
4
  module PlantUML
5
- VERSION = '0.0.15'
5
+ VERSION = '0.1.1'
6
6
  end
7
7
  end
@@ -0,0 +1,3 @@
1
+ skinparam monochrome true
2
+ skinparam backgroundColor transparent
3
+ skinparam style strictuml
@@ -0,0 +1,4 @@
1
+ @startuml
2
+ User -> (Start)
3
+ User --> (Use the application) : Label
4
+ @enduml
@@ -184,10 +184,88 @@ DOC_SVG = <<~ENDOFSTRING
184
184
  ----
185
185
  ENDOFSTRING
186
186
 
187
+ DOC_BLOCK_MACRO = <<~ENDOFSTRING
188
+ = Hello PlantUML!
189
+
190
+ .Title Of this
191
+ plantuml::test/fixtures/test.puml[]
192
+ ENDOFSTRING
193
+
194
+ DOC_BLOCK_MACRO_MISSING_FILE = <<~ENDOFSTRING
195
+ = Hello PlantUML!
196
+
197
+ .Title Of this
198
+ plantuml::test/fixtures/missing.puml[]
199
+ ENDOFSTRING
200
+
201
+ DOC_BLOCK_MACRO_INSECURE_FILE = <<~ENDOFSTRING
202
+ = Hello PlantUML!
203
+
204
+ .Title Of this
205
+ plantuml::/etc/passwd[]
206
+ ENDOFSTRING
207
+
208
+ DOC_SUBS_ATTRIBUTES = <<~ENDOFSTRING
209
+ = Hello PlantUML!
210
+ :text: Label
211
+
212
+ [plantuml, format="png", subs="attributes+"]
213
+ .Title Of this
214
+ ----
215
+ User -> (Start)
216
+ User --> (Use the application) : {text}
217
+ ----
218
+ ENDOFSTRING
219
+
220
+ DOC_CONFIG_INCLUDE = <<~ENDOFSTRING
221
+ = Hello PlantUML!
222
+ :plantuml-include: test/fixtures/config.puml
223
+
224
+ [plantuml, format="png"]
225
+ .Title Of this
226
+ ----
227
+ User -> (Start)
228
+ User --> (Use the application) : Label
229
+ ----
230
+ ENDOFSTRING
231
+
232
+ DOC_CONFIG_INCLUDE_MISSING_FILE = <<~ENDOFSTRING
233
+ = Hello PlantUML!
234
+ :plantuml-include: test/fixtures/missing.puml
235
+
236
+ [plantuml, format="png"]
237
+ .Title Of this
238
+ ----
239
+ User -> (Start)
240
+ User --> (Use the application) : Label
241
+ ----
242
+ ENDOFSTRING
243
+
244
+ DOC_CONFIG_INCLUDE_INSECURE_FILE = <<~ENDOFSTRING
245
+ = Hello PlantUML!
246
+ :plantuml-include: /etc/passwd
247
+
248
+ [plantuml, format="png"]
249
+ .Title Of this
250
+ ----
251
+ User -> (Start)
252
+ User --> (Use the application) : Label
253
+ ----
254
+ ENDOFSTRING
255
+
256
+ DOC_CONFIG_INCLUDE_MACRO_BLOCK = <<~ENDOFSTRING
257
+ = Hello PlantUML!
258
+ :plantuml-include: test/fixtures/config.puml
259
+
260
+ [plantuml, format="png"]
261
+ plantuml::test/fixtures/test.puml[]
262
+ ENDOFSTRING
263
+
187
264
  class PlantUmlTest < Test::Unit::TestCase
188
265
  GENURL = 'http://localhost:8080/plantuml/png/U9npA2v9B2efpStX2YrEBLBGjLFG20Q9Q4Bv804WIw4a8rKXiQ0W9pCviIGpFqzJmKh19p4fDOVB8JKl1QWT05kd5wq0'
189
266
  GENURL2 = 'http://localhost:8080/plantuml/png/U9npA2v9B2efpStXYdRszmqmZ8NGHh4mleAkdGAAa15G22Pc7Clba9gN0jGE00W75Cm0'
190
267
  GENURL_ENCODING = 'http://localhost:8080/plantuml/png/~1U9npA2v9B2efpStX2YrEBLBGjLFG20Q9Q4Bv804WIw4a8rKXiQ0W9pCviIGpFqzJmKh19p4fDOVB8JKl1QWT05kd5wq0'
268
+ GENURL_CONFIG = 'http://localhost:8080/plantuml/png/~1U9nDZJ4Emp08HVUSWh4PUe4ELQIktQeUW3YeiMA31NZexKEg3bc-Fly1Vp97zLxBO5lcXeeLgh2aLQKIk7OwaHdJzb7fl3oaY0P6ja34Vjeo_nOArPn-dzz62jSxN5v7r_YVZo0S-4g0hPMSqBFm23Tuuanbc8YNEDy1SzOwlG00'
191
269
  SVGGENURL = 'http://localhost:8080/plantuml/svg/~1U9npA2v9B2efpStX2YrEBLBGjLFG20Q9Q4Bv804WIw4a8rKXiQ0W9pCviIGpFqzJmKh19p4fDOVB8JKl1QWT05kd5wq0'
192
270
 
193
271
  def setup
@@ -302,6 +380,94 @@ class PlantUmlTest < Test::Unit::TestCase
302
380
  assert_equal GENURL_ENCODING, element['src']
303
381
  end
304
382
 
383
+ def test_plantuml_block_macro_processor
384
+ html = ::Asciidoctor.convert(StringIO.new(DOC_BLOCK_MACRO), backend: 'html5')
385
+ page = Nokogiri::HTML(html)
386
+
387
+ elements = page.css('img.plantuml')
388
+
389
+ assert_equal elements.size, 1
390
+
391
+ element = elements.first
392
+
393
+ assert_equal GENURL, element['src']
394
+ end
395
+
396
+ def test_should_show_file_error
397
+ html = ::Asciidoctor.convert(StringIO.new(DOC_BLOCK_MACRO_MISSING_FILE), backend: 'html5', safe: :secure)
398
+ page = Nokogiri::HTML(html)
399
+
400
+ elements = page.css('pre.plantuml-error')
401
+ assert_equal elements.size, 1
402
+ assert_includes html, 'No such file or directory'
403
+ end
404
+
405
+ def test_should_show_insecure_error
406
+ html = ::Asciidoctor.convert(StringIO.new(DOC_BLOCK_MACRO_INSECURE_FILE), backend: 'html5', safe: :secure)
407
+ page = Nokogiri::HTML(html)
408
+
409
+ elements = page.css('pre.plantuml-error')
410
+ assert_equal elements.size, 1
411
+ assert_includes html, 'is outside of jail'
412
+ end
413
+
414
+ def test_plantuml_subs_attributes
415
+ html = ::Asciidoctor.convert(StringIO.new(DOC_SUBS_ATTRIBUTES), backend: 'html5')
416
+ page = Nokogiri::HTML(html)
417
+
418
+ elements = page.css('img.plantuml')
419
+
420
+ assert_equal elements.size, 1
421
+
422
+ element = elements.first
423
+
424
+ assert_equal GENURL_ENCODING, element['src']
425
+ end
426
+
427
+ def test_plantuml_config_include
428
+ html = ::Asciidoctor.convert(StringIO.new(DOC_CONFIG_INCLUDE), backend: 'html5', safe: :secure)
429
+ page = Nokogiri::HTML(html)
430
+
431
+ elements = page.css('img.plantuml')
432
+
433
+ assert_equal elements.size, 1
434
+
435
+ element = elements.first
436
+
437
+ assert_equal GENURL_CONFIG, element['src']
438
+ end
439
+
440
+ def test_plantuml_config_include_missing_file
441
+ html = ::Asciidoctor.convert(StringIO.new(DOC_CONFIG_INCLUDE_MISSING_FILE), backend: 'html5')
442
+ page = Nokogiri::HTML(html)
443
+
444
+ elements = page.css('pre.plantuml-error')
445
+ assert_equal elements.size, 1
446
+ assert_includes html, 'No such file or directory'
447
+ end
448
+
449
+ def test_plantuml_config_include_insecure_file
450
+ html = ::Asciidoctor.convert(StringIO.new(DOC_CONFIG_INCLUDE_INSECURE_FILE), backend: 'html5', safe: :secure)
451
+ page = Nokogiri::HTML(html)
452
+
453
+ elements = page.css('pre.plantuml-error')
454
+ assert_equal elements.size, 1
455
+ assert_includes html, 'is outside of jail'
456
+ end
457
+
458
+ def test_plantuml_config_include_macro_block
459
+ html = ::Asciidoctor.convert(StringIO.new(DOC_CONFIG_INCLUDE_MACRO_BLOCK), backend: 'html5', safe: :secure)
460
+ page = Nokogiri::HTML(html)
461
+
462
+ elements = page.css('img.plantuml')
463
+
464
+ assert_equal elements.size, 1
465
+
466
+ element = elements.first
467
+
468
+ assert_equal GENURL_CONFIG, element['src']
469
+ end
470
+
305
471
  def test_plantuml_id_attribute
306
472
  html = ::Asciidoctor.convert(StringIO.new(DOC_ID), backend: 'html5')
307
473
  page = Nokogiri::HTML(html)
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-plantuml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Horacio Sanson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-28 00:00:00.000000000 Z
11
+ date: 2022-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.2.10
19
+ version: '2.2'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.2.10
26
+ version: '2.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: nokogiri
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.11'
33
+ version: 1.13.4
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: '1.11'
40
+ version: 1.13.4
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,35 +58,35 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.7'
61
+ version: '1.28'
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: '1.7'
68
+ version: '1.28'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: test-unit
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '3.3'
75
+ version: '3.5'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '3.3'
82
+ version: '3.5'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: asciidoctor
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: 1.5.6
89
+ version: 2.0.17
90
90
  - - "<"
91
91
  - !ruby/object:Gem::Version
92
92
  version: 3.0.0
@@ -96,7 +96,7 @@ dependencies:
96
96
  requirements:
97
97
  - - ">="
98
98
  - !ruby/object:Gem::Version
99
- version: 1.5.6
99
+ version: 2.0.17
100
100
  - - "<"
101
101
  - !ruby/object:Gem::Version
102
102
  version: 3.0.0
@@ -110,11 +110,14 @@ files:
110
110
  - lib/asciidoctor-plantuml.rb
111
111
  - lib/asciidoctor_plantuml/plantuml.rb
112
112
  - lib/asciidoctor_plantuml/version.rb
113
+ - test/fixtures/config.puml
114
+ - test/fixtures/test.puml
113
115
  - test/test_plantuml.rb
114
116
  homepage: https://github.com/hsanson/asciidoctor-plantuml
115
117
  licenses:
116
118
  - MIT
117
- metadata: {}
119
+ metadata:
120
+ rubygems_mfa_required: 'true'
118
121
  post_install_message:
119
122
  rdoc_options: []
120
123
  require_paths:
@@ -123,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
123
126
  requirements:
124
127
  - - ">="
125
128
  - !ruby/object:Gem::Version
126
- version: '2.5'
129
+ version: '2.6'
127
130
  required_rubygems_version: !ruby/object:Gem::Requirement
128
131
  requirements:
129
132
  - - ">="
@@ -135,4 +138,6 @@ signing_key:
135
138
  specification_version: 4
136
139
  summary: Asciidoctor support for PlantUML diagrams.
137
140
  test_files:
141
+ - test/fixtures/config.puml
142
+ - test/fixtures/test.puml
138
143
  - test/test_plantuml.rb