asciidoctor-plantuml 0.0.16 → 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: 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