asciidoctor-plantuml 0.0.16 → 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: fe7b55f293e7f815c3107f7cb42b8118b2f5cbcc2d46ddc04c003c8e855ae2ff
4
- data.tar.gz: ded1cc190a25eca2b172fc459a4f77d4f629e484f0112b5d1693686433d2197c
3
+ metadata.gz: fa9d42baca46ef240d1621640dce548f96a46e4e535a6405cace400e2495f097
4
+ data.tar.gz: b7320f06086d5230ceb3507945971f48efe988edfd159ebde0cc1c5609bc86f6
5
5
  SHA512:
6
- metadata.gz: ce55a9ec6de14f336fb5330b2a0f5d9369236c8c213fa306a59ba0f14aaddab50a40412ffc3156b16bb6e742ba8b50238f4c06768e22b7def34eedea9d4da0e9
7
- data.tar.gz: 9aa54dd2b91d173bf8225581bacb82cc2c6b2d8316ceea4f948959cb8696acb0f7f045b01c9f97a80c2476a3d7bc20fae75099c51936420c3763e581bc1bb379
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
@@ -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">'
@@ -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.16'
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,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-plantuml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.16
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: 2022-04-30 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
@@ -110,6 +110,8 @@ 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:
@@ -136,4 +138,6 @@ signing_key:
136
138
  specification_version: 4
137
139
  summary: Asciidoctor support for PlantUML diagrams.
138
140
  test_files:
141
+ - test/fixtures/config.puml
142
+ - test/fixtures/test.puml
139
143
  - test/test_plantuml.rb