asciidoctor-plantuml 0.0.15 → 0.1.1

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: 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