asciidoctor-diagram 1.4.0 → 1.5.0

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +15 -0
  3. data/README.adoc +252 -95
  4. data/README_zh-CN.adoc +333 -0
  5. data/images/asciidoctor-diagram-classes.png +0 -0
  6. data/images/asciidoctor-diagram-process.png +0 -0
  7. data/lib/{asciidoctor-diagram-java-1.3.8.jar → asciidoctor-diagram-java-1.3.10.jar} +0 -0
  8. data/lib/asciidoctor-diagram.rb +9 -9
  9. data/lib/asciidoctor-diagram/blockdiag.rb +1 -2
  10. data/lib/asciidoctor-diagram/blockdiag/extension.rb +27 -12
  11. data/lib/asciidoctor-diagram/ditaa.rb +1 -2
  12. data/lib/asciidoctor-diagram/ditaa/extension.rb +33 -48
  13. data/lib/asciidoctor-diagram/extensions.rb +85 -18
  14. data/lib/asciidoctor-diagram/graphviz.rb +1 -2
  15. data/lib/asciidoctor-diagram/graphviz/extension.rb +14 -4
  16. data/lib/asciidoctor-diagram/meme.rb +1 -2
  17. data/lib/asciidoctor-diagram/meme/extension.rb +82 -79
  18. data/lib/asciidoctor-diagram/mermaid.rb +1 -2
  19. data/lib/asciidoctor-diagram/mermaid/extension.rb +33 -25
  20. data/lib/asciidoctor-diagram/plantuml.rb +1 -2
  21. data/lib/asciidoctor-diagram/plantuml/extension.rb +33 -22
  22. data/lib/asciidoctor-diagram/salt.rb +1 -2
  23. data/lib/asciidoctor-diagram/shaape.rb +1 -2
  24. data/lib/asciidoctor-diagram/shaape/extension.rb +10 -5
  25. data/lib/asciidoctor-diagram/util/cli_generator.rb +7 -5
  26. data/lib/asciidoctor-diagram/util/java.rb +1 -1
  27. data/lib/asciidoctor-diagram/util/platform.rb +12 -1
  28. data/lib/asciidoctor-diagram/util/which.rb +16 -7
  29. data/lib/asciidoctor-diagram/version.rb +1 -1
  30. data/lib/asciidoctor-diagram/wavedrom.rb +1 -2
  31. data/lib/asciidoctor-diagram/wavedrom/extension.rb +24 -20
  32. data/lib/plantuml.jar +0 -0
  33. data/spec/blockdiag_spec.rb +8 -8
  34. data/spec/ditaa_spec.rb +7 -7
  35. data/spec/graphviz_spec.rb +7 -7
  36. data/spec/meme_spec.rb +2 -2
  37. data/spec/mermaid_spec.rb +11 -11
  38. data/spec/plantuml_spec.rb +156 -34
  39. data/spec/shaape_spec.rb +8 -8
  40. data/spec/test_helper.rb +24 -5
  41. data/spec/wavedrom_spec.rb +11 -11
  42. metadata +6 -3
@@ -1,9 +1,9 @@
1
- require 'asciidoctor-diagram/blockdiag'
2
- require 'asciidoctor-diagram/ditaa'
3
- require 'asciidoctor-diagram/graphviz'
4
- require 'asciidoctor-diagram/meme'
5
- require 'asciidoctor-diagram/mermaid'
6
- require 'asciidoctor-diagram/plantuml'
7
- require 'asciidoctor-diagram/salt'
8
- require 'asciidoctor-diagram/shaape'
9
- require 'asciidoctor-diagram/wavedrom'
1
+ require_relative 'asciidoctor-diagram/blockdiag'
2
+ require_relative 'asciidoctor-diagram/ditaa'
3
+ require_relative 'asciidoctor-diagram/graphviz'
4
+ require_relative 'asciidoctor-diagram/meme'
5
+ require_relative 'asciidoctor-diagram/mermaid'
6
+ require_relative 'asciidoctor-diagram/plantuml'
7
+ require_relative 'asciidoctor-diagram/salt'
8
+ require_relative 'asciidoctor-diagram/shaape'
9
+ require_relative 'asciidoctor-diagram/wavedrom'
@@ -1,5 +1,4 @@
1
- require 'asciidoctor/extensions'
2
- require_relative 'version'
1
+ require_relative 'extensions'
3
2
 
4
3
  Asciidoctor::Extensions.register do
5
4
  require_relative 'blockdiag/extension'
@@ -1,5 +1,6 @@
1
1
  require_relative '../extensions'
2
2
  require_relative '../util/cli_generator'
3
+ require_relative '../util/platform'
3
4
  require_relative '../util/which'
4
5
 
5
6
  module Asciidoctor
@@ -72,7 +73,17 @@ module Asciidoctor
72
73
 
73
74
  # @private
74
75
  module BlockDiag
75
- def self.define_processors(name, &init)
76
+ def self.define_processors(name)
77
+ init = Proc.new do
78
+ include ::Asciidoctor::Diagram::BlockDiag
79
+
80
+ [:png, :svg].each do |f|
81
+ register_format(f, :image) do |p, c|
82
+ blockdiag(name, p, c, f)
83
+ end
84
+ end
85
+ end
86
+
76
87
  block = Class.new(Extensions::DiagramBlockProcessor) do
77
88
  self.instance_eval &init
78
89
  end
@@ -84,20 +95,24 @@ module Asciidoctor
84
95
 
85
96
  ::Asciidoctor::Diagram.const_set("#{name}BlockMacroProcessor", block_macro)
86
97
  end
87
- end
88
98
 
89
- ['BlockDiag', 'SeqDiag', 'ActDiag', 'NwDiag', 'RackDiag', 'PacketDiag'].each do |tool|
90
- BlockDiag.define_processors(tool) do
91
- include Which
99
+ include Which
92
100
 
93
- [:png, :svg].each do |f|
94
- register_format(f, :image) do |c, p|
95
- CliGenerator.generate_stdin(which(p, tool.downcase), f.to_s, c.to_s) do |tool_path, output_path|
96
- [tool_path, '-o', output_path, "-T#{f.to_s}", '-']
97
- end
98
- end
101
+ def blockdiag(tool, parent, source, format)
102
+ cmd_name = tool.downcase
103
+
104
+ # On Debian based systems the Python 3.x packages python3-(act|block|nw|seq)diag executables with
105
+ # a '3' suffix.
106
+ alt_cmd_name = "#{tool.downcase}3"
107
+
108
+ CliGenerator.generate_stdin(which(parent, cmd_name, :alt_cmds => [alt_cmd_name]), format.to_s, source.to_s) do |tool_path, output_path|
109
+ [tool_path, '-o', Platform.native_path(output_path), "-T#{format.to_s}", '-']
99
110
  end
100
111
  end
101
112
  end
113
+
114
+ ['BlockDiag', 'SeqDiag', 'ActDiag', 'NwDiag', 'RackDiag', 'PacketDiag'].each do |tool|
115
+ BlockDiag.define_processors(tool)
116
+ end
102
117
  end
103
- end
118
+ end
@@ -1,5 +1,4 @@
1
- require 'asciidoctor/extensions'
2
- require_relative 'version'
1
+ require_relative 'extensions'
3
2
 
4
3
  Asciidoctor::Extensions.register do
5
4
  require_relative 'ditaa/extension'
@@ -7,19 +7,49 @@ module Asciidoctor
7
7
  module Diagram
8
8
  # @private
9
9
  module Ditaa
10
+ OPTIONS = {
11
+ 'scale' => lambda { |o, v| o << '--scale' << v if v },
12
+ 'tabs' => lambda { |o, v| o << '--tabs' << v if v },
13
+ 'background' => lambda { |o, v| o << '--background' << v if v },
14
+ 'antialias' => lambda { |o, v| o << '--no-antialias' if v == 'false' },
15
+ 'separation' => lambda { |o, v| o << '--no-separation' if v == 'false'},
16
+ 'round-corners' => lambda { |o, v| o << '--round-corners' if v == 'true'},
17
+ 'shadows' => lambda { |o, v| o << '--no-shadows' if v == 'false'},
18
+ 'debug' => lambda { |o, v| o << '--debug' if v == 'true'},
19
+ 'fixed-slope' => lambda { |o, v| o << '--fixed-slope' if v == 'true'},
20
+ 'transparent' => lambda { |o, v| o << '--transparent' if v == 'true'}
21
+ }
22
+
10
23
  JARS = ['ditaamini-0.10.jar'].map do |jar|
11
24
  File.expand_path File.join('../..', jar), File.dirname(__FILE__)
12
25
  end
13
26
  Java.classpath.concat JARS
14
27
 
15
- def ditaa(code, source)
28
+ def self.included(mod)
29
+ mod.register_format(:png, :image) do |parent, source|
30
+ ditaa(parent, source)
31
+ end
32
+ end
33
+
34
+ def ditaa(parent, source)
16
35
  Java.load
17
36
 
37
+ global_attributes = parent.document.attributes
38
+
39
+ options = []
40
+
41
+ OPTIONS.keys.each do |key|
42
+ value = source.attributes.delete(key) || global_attributes["ditaa-option-#{key}"]
43
+ OPTIONS[key].call(options, value)
44
+ end
45
+
46
+ options = options.join(' ')
47
+
18
48
  response = Java.send_request(
19
49
  :url => '/ditaa',
20
- :body => code,
50
+ :body => source.to_s,
21
51
  :headers => {
22
- 'X-Options' => source.options
52
+ 'X-Options' => options
23
53
  }
24
54
  )
25
55
 
@@ -29,51 +59,6 @@ module Asciidoctor
29
59
 
30
60
  response[:body]
31
61
  end
32
-
33
- def self.included(mod)
34
- mod.register_format(:png, :image) do |c, _, source|
35
- ditaa(c.to_s, source)
36
- end
37
- end
38
-
39
- def create_source(parent, reader, attributes)
40
- source = super(parent, reader, attributes)
41
- source.extend DitaaSource
42
-
43
- source.init_ditaa_options(parent, attributes)
44
-
45
- source
46
- end
47
-
48
- module DitaaSource
49
- attr_reader :options
50
-
51
- OPTIONS = {
52
- 'scale' => lambda { |o, v| o << '--scale' << v if v },
53
- 'tabs' => lambda { |o, v| o << '--tabs' << v if v },
54
- 'background' => lambda { |o, v| o << '--background' << v if v },
55
- 'antialias' => lambda { |o, v| o << '--no-antialias' if v == 'false' },
56
- 'separation' => lambda { |o, v| o << '--no-separation' if v == 'false'},
57
- 'round-corners' => lambda { |o, v| o << '--round-corners' if v == 'true'},
58
- 'shadows' => lambda { |o, v| o << '--no-shadows' if v == 'false'},
59
- 'debug' => lambda { |o, v| o << '--debug' if v == 'true'},
60
- 'fixed-slope' => lambda { |o, v| o << '--fixed-slope' if v == 'true'},
61
- 'transparent' => lambda { |o, v| o << '--transparent' if v == 'true'}
62
- }
63
-
64
- def init_ditaa_options(parent, attributes)
65
- global_attributes = parent.document.attributes
66
-
67
- options = []
68
-
69
- OPTIONS.keys.each do |key|
70
- value = attributes.delete(key) || global_attributes["ditaa-option-#{key}"]
71
- OPTIONS[key].call(options, value)
72
- end
73
-
74
- @options = options.join(' ')
75
- end
76
- end
77
62
  end
78
63
 
79
64
  class DitaaBlockProcessor < Extensions::DiagramBlockProcessor
@@ -1,7 +1,9 @@
1
+ require 'asciidoctor' unless defined? ::Asciidoctor::VERSION
1
2
  require 'asciidoctor/extensions'
2
3
  require 'digest'
3
4
  require 'json'
4
5
  require 'fileutils'
6
+ require_relative 'version'
5
7
  require_relative 'util/java'
6
8
  require_relative 'util/gif'
7
9
  require_relative 'util/png'
@@ -143,8 +145,9 @@ module Asciidoctor
143
145
  def create_image_block(parent, source, format, generator_info)
144
146
  image_name = "#{source.image_name}.#{format}"
145
147
  image_dir = image_output_dir(parent)
148
+ cache_dir = cache_dir(parent)
146
149
  image_file = parent.normalize_system_path image_name, image_dir
147
- metadata_file = parent.normalize_system_path "#{image_name}.cache", image_dir
150
+ metadata_file = parent.normalize_system_path "#{image_name}.cache", cache_dir
148
151
 
149
152
  if File.exists? metadata_file
150
153
  metadata = File.open(metadata_file, 'r') { |f| JSON.load f }
@@ -157,7 +160,7 @@ module Asciidoctor
157
160
  if !File.exists?(image_file) || source.should_process?(image_file, metadata)
158
161
  params = IMAGE_PARAMS[format]
159
162
 
160
- result = instance_exec(source, parent, source, &generator_info[:generator])
163
+ result = instance_exec(parent, source, &generator_info[:generator])
161
164
 
162
165
  result.force_encoding(params[:encoding])
163
166
 
@@ -166,6 +169,8 @@ module Asciidoctor
166
169
 
167
170
  FileUtils.mkdir_p(File.dirname(image_file)) unless Dir.exist?(File.dirname(image_file))
168
171
  File.open(image_file, 'wb') { |f| f.write result }
172
+
173
+ FileUtils.mkdir_p(File.dirname(metadata_file)) unless Dir.exist?(File.dirname(metadata_file))
169
174
  File.open(metadata_file, 'w') { |f| JSON.dump(metadata, f) }
170
175
  end
171
176
 
@@ -212,23 +217,30 @@ module Asciidoctor
212
217
  def image_output_dir(parent)
213
218
  document = parent.document
214
219
 
215
- images_dir = document.attr('imagesoutdir')
220
+ images_dir = parent.attr('imagesoutdir')
216
221
 
217
222
  if images_dir
218
223
  base_dir = nil
219
224
  else
220
- base_dir = document.attr('outdir') || (document.respond_to?(:options) && document.options[:to_dir])
221
- images_dir = document.attr('imagesdir')
225
+ base_dir = parent.attr('outdir') || (document.respond_to?(:options) && document.options[:to_dir])
226
+ images_dir = parent.attr('imagesdir')
222
227
  end
223
228
 
224
229
  parent.normalize_system_path(images_dir, base_dir)
225
230
  end
226
231
 
232
+ def cache_dir(parent)
233
+ document = parent.document
234
+ cache_dir = '.asciidoctor/diagram'
235
+ base_dir = parent.attr('outdir') || (document.respond_to?(:options) && document.options[:to_dir])
236
+ parent.normalize_system_path(cache_dir, base_dir)
237
+ end
238
+
227
239
  def create_literal_block(parent, source, generator_info)
228
240
  literal_attributes = source.attributes
229
241
  literal_attributes.delete('target')
230
242
 
231
- result = instance_exec(source, parent, &generator_info[:generator])
243
+ result = instance_exec(parent, source, &generator_info[:generator])
232
244
 
233
245
  result.force_encoding(Encoding::UTF_8)
234
246
  Asciidoctor::Block.new parent, :literal, :source => result, :attributes => literal_attributes
@@ -249,7 +261,7 @@ module Asciidoctor
249
261
  #
250
262
  # @return [ReaderSource] a ReaderSource
251
263
  def create_source(parent, reader, attributes)
252
- ReaderSource.new(reader, attributes)
264
+ ReaderSource.new(parent, reader, attributes)
253
265
  end
254
266
  end
255
267
 
@@ -265,7 +277,7 @@ module Asciidoctor
265
277
  #
266
278
  # @return [FileSource] a FileSource
267
279
  def create_source(parent, target, attributes)
268
- FileSource.new(target.empty? ? nil : parent.normalize_system_path(target, parent.document.base_dir), attributes)
280
+ FileSource.new(parent, target.empty? ? nil : parent.normalize_system_path(target, parent.attr('docdir')), attributes)
269
281
  end
270
282
  end
271
283
 
@@ -284,6 +296,28 @@ module Asciidoctor
284
296
  raise NotImplementedError.new
285
297
  end
286
298
 
299
+ # Get the value for the specified attribute. First look in the attributes on
300
+ # this node and return the value of the attribute if found. Otherwise, if
301
+ # this node is a child of the Document node, look in the attributes of the
302
+ # Document node and return the value of the attribute if found. Otherwise,
303
+ # return the default value, which defaults to nil.
304
+ #
305
+ # @param name [String, Symbol] the name of the attribute to lookup
306
+ # @param default_value [Object] the value to return if the attribute is not found
307
+ # @inherit [Boolean] indicates whether to check for the attribute on the AsciiDoctor::Document if not found on this node
308
+ #
309
+ # @return the value of the attribute or the default value if the attribute is not found in the attributes of this node or the document node
310
+ # @abstract
311
+ def attr(name, default_value = nil, inherit = true)
312
+ raise NotImplementedError.new
313
+ end
314
+
315
+ # @return [String] the base directory against which relative paths in this diagram should be resolved
316
+ # @abstract
317
+ def base_dir
318
+ raise NotImplementedError.new
319
+ end
320
+
287
321
  # Alias for code
288
322
  def to_s
289
323
  code
@@ -316,12 +350,23 @@ module Asciidoctor
316
350
 
317
351
  attr_reader :attributes
318
352
 
319
- def initialize(attributes)
353
+ def initialize(parent, attributes)
354
+ @parent = parent
320
355
  @attributes = attributes
321
356
  end
322
357
 
323
358
  def image_name
324
- @attributes['target'] || ('diag-' + checksum)
359
+ attr('target', 'diag-' + checksum)
360
+ end
361
+
362
+ def attr(name, default_value=nil, inherit=nil)
363
+ name = name.to_s if ::Symbol === name
364
+
365
+ if inherit
366
+ @attributes[name] || @parent.attr(name, default_value, true)
367
+ else
368
+ @attributes[name] || default_value
369
+ end
325
370
  end
326
371
 
327
372
  def should_process?(image_file, image_metadata)
@@ -336,11 +381,21 @@ module Asciidoctor
336
381
  @checksum ||= compute_checksum(code)
337
382
  end
338
383
 
384
+ protected
385
+ def resolve_diagram_subs
386
+ if @attributes.key? 'subs'
387
+ subs = @parent.resolve_block_subs @attributes['subs'], nil, 'diagram'
388
+ subs.empty? ? nil : subs
389
+ else
390
+ nil
391
+ end
392
+ end
393
+
339
394
  private
340
395
  def compute_checksum(code)
341
396
  md5 = Digest::MD5.new
342
397
  md5 << code
343
- attributes.each do |k, v|
398
+ @attributes.each do |k, v|
344
399
  md5 << k.to_s if k
345
400
  md5 << v.to_s if v
346
401
  end
@@ -352,23 +407,31 @@ module Asciidoctor
352
407
  class ReaderSource < BasicSource
353
408
  include DiagramSource
354
409
 
355
- def initialize(reader, attributes)
356
- super(attributes)
410
+ def initialize(parent, reader, attributes)
411
+ super(parent, attributes)
357
412
  @reader = reader
358
413
  end
359
414
 
415
+ def base_dir
416
+ attr('docdir', nil, true)
417
+ end
418
+
360
419
  def code
361
- @code ||= @reader.lines.join("\n")
420
+ @code ||= @parent.apply_subs(@reader.lines, resolve_diagram_subs).join("\n")
362
421
  end
363
422
  end
364
423
 
365
424
  # A diagram source that retrieves the code for a diagram from an external source file.
366
425
  class FileSource < BasicSource
367
- def initialize(file_name, attributes)
368
- super(attributes)
426
+ def initialize(parent, file_name, attributes)
427
+ super(parent, attributes)
369
428
  @file_name = file_name
370
429
  end
371
430
 
431
+ def base_dir
432
+ File.dirname(@file_name)
433
+ end
434
+
372
435
  def image_name
373
436
  if @attributes['target']
374
437
  super
@@ -384,12 +447,16 @@ module Asciidoctor
384
447
  end
385
448
 
386
449
  def code
450
+ @code ||= read_code
451
+ end
452
+
453
+ def read_code
387
454
  if @file_name
388
455
  lines = File.readlines(@file_name)
389
456
  lines = ::Asciidoctor::Helpers.normalize_lines(lines)
390
- @code ||= lines.join("\n")
457
+ @parent.apply_subs(lines, resolve_diagram_subs).join("\n")
391
458
  else
392
- @code ||= ''
459
+ ''
393
460
  end
394
461
  end
395
462
  end
@@ -1,5 +1,4 @@
1
- require 'asciidoctor/extensions'
2
- require_relative 'version'
1
+ require_relative 'extensions'
3
2
 
4
3
  Asciidoctor::Extensions.register do
5
4
  require_relative 'graphviz/extension'
@@ -1,5 +1,6 @@
1
1
  require_relative '../extensions'
2
2
  require_relative '../util/cli_generator'
3
+ require_relative '../util/platform'
3
4
  require_relative '../util/which'
4
5
 
5
6
  module Asciidoctor
@@ -10,13 +11,22 @@ module Asciidoctor
10
11
 
11
12
  def self.included(mod)
12
13
  [:png, :svg].each do |f|
13
- mod.register_format(f, :image) do |c, p|
14
- CliGenerator.generate_stdin(which(p, 'dot', :attr_names => ['dot', 'graphvizdot']), f.to_s, c.to_s) do |tool_path, output_path|
15
- [tool_path, "-o#{output_path}", "-T#{f.to_s}"]
16
- end
14
+ mod.register_format(f, :image) do |parent, source|
15
+ graphviz(parent, source, f)
17
16
  end
18
17
  end
19
18
  end
19
+
20
+ def graphviz(parent, source, format)
21
+ CliGenerator.generate_stdin(which(parent, 'dot', :alt_attrs => ['graphvizdot']), format.to_s, source.to_s) do |tool_path, output_path|
22
+ args = [tool_path, "-o#{Platform.native_path(output_path)}", "-T#{format.to_s}"]
23
+
24
+ layout = source.attr('layout')
25
+ args << "-K#{layout}" if layout
26
+
27
+ args
28
+ end
29
+ end
20
30
  end
21
31
 
22
32
  class GraphvizBlockProcessor < Extensions::DiagramBlockProcessor