asciidoctor-diagram 1.5.19 → 2.0.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 (69) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.adoc +10 -0
  3. data/README.adoc +22 -9
  4. data/examples/features.adoc +2 -2
  5. data/lib/asciidoctor-diagram.rb +1 -0
  6. data/lib/asciidoctor-diagram/a2s/converter.rb +55 -0
  7. data/lib/asciidoctor-diagram/a2s/extension.rb +6 -52
  8. data/lib/asciidoctor-diagram/blockdiag/converter.rb +37 -0
  9. data/lib/asciidoctor-diagram/blockdiag/extension.rb +9 -116
  10. data/lib/asciidoctor-diagram/bpmn.rb +7 -0
  11. data/lib/asciidoctor-diagram/bpmn/converter.rb +62 -0
  12. data/lib/asciidoctor-diagram/bpmn/extension.rb +14 -0
  13. data/lib/asciidoctor-diagram/diagram_converter.rb +19 -0
  14. data/lib/asciidoctor-diagram/diagram_processor.rb +320 -0
  15. data/lib/asciidoctor-diagram/diagram_source.rb +275 -0
  16. data/lib/asciidoctor-diagram/ditaa/converter.rb +86 -0
  17. data/lib/asciidoctor-diagram/ditaa/extension.rb +6 -71
  18. data/lib/asciidoctor-diagram/erd/converter.rb +31 -0
  19. data/lib/asciidoctor-diagram/erd/extension.rb +6 -35
  20. data/lib/asciidoctor-diagram/gnuplot/converter.rb +63 -0
  21. data/lib/asciidoctor-diagram/gnuplot/extension.rb +6 -62
  22. data/lib/asciidoctor-diagram/graphviz/converter.rb +32 -0
  23. data/lib/asciidoctor-diagram/graphviz/extension.rb +6 -35
  24. data/lib/asciidoctor-diagram/http/server.rb +127 -0
  25. data/lib/asciidoctor-diagram/lilypond/converter.rb +54 -0
  26. data/lib/asciidoctor-diagram/lilypond/extension.rb +6 -53
  27. data/lib/asciidoctor-diagram/meme/converter.rb +122 -0
  28. data/lib/asciidoctor-diagram/meme/extension.rb +5 -107
  29. data/lib/asciidoctor-diagram/mermaid/converter.rb +178 -0
  30. data/lib/asciidoctor-diagram/mermaid/extension.rb +6 -159
  31. data/lib/asciidoctor-diagram/msc/converter.rb +35 -0
  32. data/lib/asciidoctor-diagram/msc/extension.rb +6 -36
  33. data/lib/asciidoctor-diagram/nomnoml/converter.rb +25 -0
  34. data/lib/asciidoctor-diagram/nomnoml/extension.rb +6 -28
  35. data/lib/asciidoctor-diagram/plantuml/converter.rb +115 -0
  36. data/lib/asciidoctor-diagram/plantuml/extension.rb +10 -119
  37. data/lib/asciidoctor-diagram/shaape/converter.rb +25 -0
  38. data/lib/asciidoctor-diagram/shaape/extension.rb +6 -28
  39. data/lib/asciidoctor-diagram/smcat/converter.rb +44 -0
  40. data/lib/asciidoctor-diagram/smcat/extension.rb +6 -42
  41. data/lib/asciidoctor-diagram/svgbob/converter.rb +25 -0
  42. data/lib/asciidoctor-diagram/svgbob/extension.rb +6 -28
  43. data/lib/asciidoctor-diagram/syntrax/converter.rb +55 -0
  44. data/lib/asciidoctor-diagram/syntrax/extension.rb +6 -51
  45. data/lib/asciidoctor-diagram/tikz/converter.rb +56 -0
  46. data/lib/asciidoctor-diagram/tikz/extension.rb +6 -60
  47. data/lib/asciidoctor-diagram/umlet/converter.rb +24 -0
  48. data/lib/asciidoctor-diagram/umlet/extension.rb +6 -28
  49. data/lib/asciidoctor-diagram/util/java.rb +1 -1
  50. data/lib/asciidoctor-diagram/util/java_socket.rb +7 -9
  51. data/lib/asciidoctor-diagram/util/which.rb +0 -29
  52. data/lib/asciidoctor-diagram/vega/converter.rb +47 -0
  53. data/lib/asciidoctor-diagram/vega/extension.rb +6 -44
  54. data/lib/asciidoctor-diagram/version.rb +1 -1
  55. data/lib/asciidoctor-diagram/wavedrom/converter.rb +50 -0
  56. data/lib/asciidoctor-diagram/wavedrom/extension.rb +6 -54
  57. data/lib/ditaa-1.3.14.jar +0 -0
  58. data/lib/plantuml-1.3.14.jar +0 -0
  59. data/lib/plantuml.jar +0 -0
  60. data/lib/server-1.3.14.jar +0 -0
  61. data/spec/bpmn-example.xml +44 -0
  62. data/spec/bpmn_spec.rb +96 -0
  63. data/spec/mermaid_spec.rb +33 -1
  64. data/spec/plantuml_spec.rb +89 -0
  65. metadata +37 -8
  66. data/lib/asciidoctor-diagram/extensions.rb +0 -568
  67. data/lib/ditaa-1.3.13.jar +0 -0
  68. data/lib/plantuml-1.3.13.jar +0 -0
  69. data/lib/server-1.3.13.jar +0 -0
@@ -0,0 +1,127 @@
1
+ require 'base64'
2
+ require 'json'
3
+ require 'sinatra/base'
4
+ require 'zlib'
5
+
6
+ require_relative '../diagram_source'
7
+ require_relative '../graphviz/converter'
8
+ require_relative '../util/which'
9
+
10
+ module Asciidoctor
11
+ module Diagram
12
+ class Server < Sinatra::Base
13
+ get '/:type/:format/:source' do
14
+ type = params['type']
15
+ accepts = lambda { |t| params['format'].downcase.to_sym == t }
16
+ raw_source = params['source']
17
+ decoded_source = Base64.urlsafe_decode64(raw_source)
18
+ decompressed_source = Zlib::Inflate.inflate(decoded_source)
19
+ source = decompressed_source
20
+ render_diagram(type, accepts, source, {})
21
+ end
22
+
23
+ post '/' do
24
+ params = JSON.parse(request.body.read)
25
+ type = params['diagram_type']
26
+ accepts = lambda { |t| params['output_format'].downcase.to_sym == t }
27
+ source = params['diagram_source']
28
+ render_diagram(type, accepts, source, {})
29
+ end
30
+
31
+ post '/:type' do
32
+ type = params['type'].to_sym
33
+ r = request
34
+ accepts = lambda { |t| r.accept?(to_mime_type(t)) }
35
+ source = request.body.read
36
+ render_diagram(type, accepts, source, {})
37
+ end
38
+
39
+ post '/:type/:format' do
40
+ type = params['type'].to_sym
41
+ accepts = lambda { |t| params['format'].downcase.to_sym == t }
42
+ source = request.body.read
43
+ render_diagram(type, accepts, source, {})
44
+ end
45
+
46
+ def to_mime_type(type)
47
+ case type
48
+ when :pdf
49
+ 'application/pdf'
50
+ when :png
51
+ 'image/png'
52
+ when :svg
53
+ 'image/svg'
54
+ when :txt
55
+ 'text/plain'
56
+ else
57
+ nil
58
+ end
59
+ end
60
+
61
+ def get_converter(type)
62
+ case type
63
+ when :graphviz
64
+ GraphvizConverter.new
65
+ else
66
+ nil
67
+ end
68
+ end
69
+
70
+ def render_diagram(type, accepts, code, attributes)
71
+ converter = get_converter(type.downcase.to_sym)
72
+ return [500, "Unsupported diagram type #{type}"] unless converter
73
+
74
+ format = converter.supported_formats.find {|f| accepts.call(f)}
75
+ return [500, "Could not determine supported output format"] unless format
76
+
77
+ source = ServerSource.new(code, attributes)
78
+ options = converter.collect_options(source, type.downcase)
79
+ diagram = converter.convert(source, format, options)
80
+
81
+ content_type to_mime_type(format)
82
+ diagram
83
+ end
84
+ end
85
+
86
+ class ServerSource
87
+ include Asciidoctor::Diagram::DiagramSource
88
+
89
+ def initialize(source, attributes)
90
+ @source = source
91
+ @attributes = attributes
92
+ end
93
+
94
+ def attr(name, default_value = nil, inherit = nil)
95
+ @attributes[name] || default_value
96
+ end
97
+
98
+ def base_dir
99
+ nil
100
+ end
101
+
102
+ def code
103
+ @source
104
+ end
105
+
106
+ def config
107
+ {}
108
+ end
109
+
110
+ def find_command(cmd, options = nil)
111
+ Asciidoctor::Diagram::Which.which(cmd, options)
112
+ end
113
+
114
+ def resolve_path(target, start = nil)
115
+ target
116
+ end
117
+
118
+ def image_name
119
+ "image"
120
+ end
121
+
122
+ def should_process?(image_file, image_metadata)
123
+ true
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,54 @@
1
+ require_relative '../diagram_converter'
2
+ require_relative '../util/cli_generator'
3
+ require_relative '../util/platform'
4
+
5
+ module Asciidoctor
6
+ module Diagram
7
+ # @private
8
+ class LilypondConverter
9
+ include DiagramConverter
10
+ include CliGenerator
11
+
12
+
13
+ def supported_formats
14
+ [:png, :pdf]
15
+ end
16
+
17
+ def collect_options(source, name)
18
+ {
19
+ :resolution => source.attr('resolution', nil, name)
20
+ }
21
+ end
22
+
23
+ def convert(source, format, options)
24
+ code = <<-EOF
25
+ \\paper{
26
+ oddFooterMarkup=##f
27
+ oddHeaderMarkup=##f
28
+ bookTitleMarkup=##f
29
+ scoreTitleMarkup=##f
30
+ }
31
+
32
+ EOF
33
+ code << source.to_s
34
+
35
+ resolution = options[:resolution]
36
+
37
+ generate_stdin(source.find_command('lilypond'), format.to_s, code) do |tool_path, output_path|
38
+ args = [tool_path, '-daux-files=#f', '-dbackend=eps', '-dno-gs-load-fonts', '-dinclude-eps-fonts', '-o', Platform.native_path(output_path), '-f', format.to_s]
39
+
40
+ args << '-dsafe'
41
+ args << "-dresolution=#{resolution}" if resolution
42
+ args << "-dpixmap-format=pngalpha" if format == :png
43
+
44
+ args << '-'
45
+
46
+ {
47
+ :args => args,
48
+ :out_file => "#{output_path}.#{format.to_s}"
49
+ }
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,61 +1,14 @@
1
- require_relative '../extensions'
2
- require_relative '../util/cli_generator'
3
- require_relative '../util/platform'
4
- require_relative '../util/which'
1
+ require_relative 'converter'
2
+ require_relative '../diagram_processor'
5
3
 
6
4
  module Asciidoctor
7
5
  module Diagram
8
- # @private
9
- module Lilypond
10
- include CliGenerator
11
- include Which
12
-
13
- def self.included(mod)
14
- [:png, :pdf].each do |f|
15
- mod.register_format(f, :image) do |parent, source|
16
- lilypond(parent, source, f)
17
- end
18
- end
19
- end
20
-
21
- def lilypond(parent, source, format)
22
- code = <<-EOF
23
- \\paper{
24
- oddFooterMarkup=##f
25
- oddHeaderMarkup=##f
26
- bookTitleMarkup=##f
27
- scoreTitleMarkup=##f
28
- }
29
-
30
- EOF
31
- code << source.to_s
32
-
33
- inherit_prefix = name
34
- resolution = source.attr('resolution', nil, inherit_prefix)
35
-
36
- generate_stdin(which(parent, 'lilypond'), format.to_s, code) do |tool_path, output_path|
37
- args = [tool_path, '-daux-files=#f', '-dbackend=eps', '-dno-gs-load-fonts', '-dinclude-eps-fonts', '-o', Platform.native_path(output_path), '-f', format.to_s]
38
-
39
- args << '-dsafe'
40
- args << "-dresolution=#{resolution}" if resolution
41
- args << "-dpixmap-format=pngalpha" if format == :png
42
-
43
- args << '-'
44
-
45
- {
46
- :args => args,
47
- :out_file => "#{output_path}.#{format.to_s}"
48
- }
49
- end
50
- end
51
- end
52
-
53
- class LilypondBlockProcessor < Extensions::DiagramBlockProcessor
54
- include Lilypond
6
+ class LilypondBlockProcessor < DiagramBlockProcessor
7
+ use_converter LilypondConverter
55
8
  end
56
9
 
57
- class LilypondBlockMacroProcessor < Extensions::DiagramBlockMacroProcessor
58
- include Lilypond
10
+ class LilypondBlockMacroProcessor < DiagramBlockMacroProcessor
11
+ use_converter LilypondConverter
59
12
  end
60
13
  end
61
14
  end
@@ -0,0 +1,122 @@
1
+ require_relative '../diagram_converter'
2
+ require_relative '../util/cli_generator'
3
+ require 'tempfile'
4
+ require 'open3'
5
+
6
+ module Asciidoctor
7
+ module Diagram
8
+ # @private
9
+ class MemeConverter
10
+ include DiagramConverter
11
+
12
+
13
+ def supported_formats
14
+ [:png, :gif]
15
+ end
16
+
17
+
18
+ def collect_options(source, name)
19
+ bg_img = source.attr('background', nil, name)
20
+ raise "background attribute is required" unless bg_img
21
+
22
+ options = source.attr('options', '', name).split(',')
23
+
24
+ {
25
+ :bg_img => bg_img,
26
+ :top_label => source.attr('top'),
27
+ :bottom_label => source.attr('bottom'),
28
+ :fill_color => source.attr('fillcolor', nil, name) || source.attr('fill-color', nil, name),
29
+ :stroke_color => source.attr('strokecolor', nil, name) || source.attr('stroke-color', nil, name),
30
+ :stroke_width => source.attr('strokewidth', nil, name) || source.attr('stroke-width', nil, name),
31
+ :font => source.attr('font', 'Impact', name),
32
+ :noupcase => options.include?('noupcase'),
33
+ }
34
+ end
35
+
36
+ def convert(source, format, options)
37
+ convert = source.find_command('convert')
38
+ identify = source.find_command('identify')
39
+
40
+ bg_img = options[:bg_img]
41
+ raise "background attribute is required" unless bg_img
42
+
43
+ bg_img = source.resolve_path(bg_img, source.attr('imagesdir'))
44
+
45
+ top_label = options[:top]
46
+ bottom_label = options[:bottom]
47
+ fill_color = options[:fill_color] || 'white'
48
+ stroke_color = options[:stroke_color] || 'black'
49
+ stroke_width = options[:stroke_width] || '2'
50
+ font = options[:font] || 'Impact'
51
+ noupcase = options[:noupcase]
52
+
53
+ dimensions = Cli.run(identify, '-format', '%w %h', bg_img)[:out].match(/(?<w>\d+) (?<h>\d+)/)
54
+ bg_width = dimensions['w'].to_i
55
+ bg_height = dimensions['h'].to_i
56
+ label_width = bg_width
57
+ label_height = bg_height / 5
58
+
59
+ if top_label
60
+ top_img = Tempfile.new(['meme', '.png'])
61
+ Cli.run(
62
+ convert,
63
+ '-background', 'none',
64
+ '-fill', fill_color,
65
+ '-stroke', stroke_color,
66
+ '-strokewidth', stroke_width,
67
+ '-font', font,
68
+ '-size', "#{label_width}x#{label_height}",
69
+ '-gravity', 'north',
70
+ "label:#{prepare_label(top_label, noupcase)}",
71
+ top_img.path
72
+ )
73
+ else
74
+ top_img = nil
75
+ end
76
+
77
+ if bottom_label
78
+ bottom_img = Tempfile.new(['meme', '.png'])
79
+ Cli.run(
80
+ convert,
81
+ '-background', 'none',
82
+ '-fill', fill_color,
83
+ '-stroke', stroke_color,
84
+ '-strokewidth', stroke_width,
85
+ '-font', font,
86
+ '-size', "#{label_width}x#{label_height}",
87
+ '-gravity', 'south',
88
+ "label:#{prepare_label(bottom_label, noupcase)}",
89
+ bottom_img.path
90
+ )
91
+ else
92
+ bottom_img = nil
93
+ end
94
+
95
+ final_img = Tempfile.new(['meme', ".#{format.to_s}"])
96
+
97
+ args = [convert, bg_img]
98
+ if top_img
99
+ args << top_img.path << '-geometry' << '+0+0' << '-composite'
100
+ end
101
+
102
+ if bottom_img
103
+ args << bottom_img.path << '-geometry' << "+0+#{bg_height - label_height}" << '-composite'
104
+ end
105
+
106
+ args << final_img.path
107
+
108
+ Cli.run(*args)
109
+
110
+ File.binread(final_img)
111
+ end
112
+
113
+ private
114
+
115
+ def prepare_label(label, noupcase)
116
+ label = label.upcase unless noupcase
117
+ label = label.gsub(' // ', '\n')
118
+ label
119
+ end
120
+ end
121
+ end
122
+ end
@@ -1,112 +1,10 @@
1
- require_relative '../extensions'
2
- require_relative '../util/cli_generator'
3
- require_relative '../util/which'
4
- require 'tempfile'
5
- require 'open3'
1
+ require_relative 'converter'
2
+ require_relative '../diagram_processor'
6
3
 
7
4
  module Asciidoctor
8
5
  module Diagram
9
- # @private
10
- module Meme
11
- include Which
12
-
13
- def self.included(mod)
14
- [:png, :gif].each do |format|
15
- mod.register_format(format, :image) do |parent, source|
16
- meme(parent, source, format)
17
- end
18
- end
19
- end
20
-
21
- def meme(parent_block, source, format)
22
- convert = which(parent_block, 'convert')
23
- identify = which(parent_block, 'identify')
24
- inherit_prefix = name
25
-
26
- bg_img = source.attr('background', nil, inherit_prefix)
27
- raise "background attribute is required" unless bg_img
28
-
29
- bg_img = parent_block.normalize_system_path(bg_img, parent_block.attr('imagesdir'))
30
-
31
- top_label = source.attr('top')
32
- bottom_label = source.attr('bottom')
33
- fill_color = source.attr('fillColor', 'white', inherit_prefix)
34
- stroke_color = source.attr('strokeColor', 'black', inherit_prefix)
35
- stroke_width = source.attr('strokeWidth', '2', inherit_prefix)
36
- font = source.attr('font', 'Impact', inherit_prefix)
37
- options = source.attr('options', '', inherit_prefix).split(',')
38
- noupcase = options.include?('noupcase')
39
-
40
- dimensions = Cli.run(identify, '-format', '%w %h', bg_img)[:out].match(/(?<w>\d+) (?<h>\d+)/)
41
- bg_width = dimensions['w'].to_i
42
- bg_height = dimensions['h'].to_i
43
- label_width = bg_width
44
- label_height = bg_height / 5
45
-
46
- if top_label
47
- top_img = Tempfile.new(['meme', '.png'])
48
- Cli.run(
49
- convert,
50
- '-background', 'none',
51
- '-fill', fill_color,
52
- '-stroke', stroke_color,
53
- '-strokewidth', stroke_width,
54
- '-font', font,
55
- '-size', "#{label_width}x#{label_height}",
56
- '-gravity', 'north',
57
- "label:#{prepare_label(top_label, noupcase)}",
58
- top_img.path
59
- )
60
- else
61
- top_img = nil
62
- end
63
-
64
- if bottom_label
65
- bottom_img = Tempfile.new(['meme', '.png'])
66
- Cli.run(
67
- convert,
68
- '-background', 'none',
69
- '-fill', fill_color,
70
- '-stroke', stroke_color,
71
- '-strokewidth', stroke_width,
72
- '-font', font,
73
- '-size', "#{label_width}x#{label_height}",
74
- '-gravity', 'south',
75
- "label:#{prepare_label(bottom_label, noupcase)}",
76
- bottom_img.path
77
- )
78
- else
79
- bottom_img = nil
80
- end
81
-
82
- final_img = Tempfile.new(['meme', ".#{format.to_s}"])
83
-
84
- args = [convert, bg_img]
85
- if top_img
86
- args << top_img.path << '-geometry'<< '+0+0' << '-composite'
87
- end
88
-
89
- if bottom_img
90
- args << bottom_img.path << '-geometry'<< "+0+#{bg_height - label_height}" << '-composite'
91
- end
92
-
93
- args << final_img.path
94
-
95
- Cli.run(*args)
96
-
97
- File.binread(final_img)
98
- end
99
-
100
- private
101
- def prepare_label(label, noupcase)
102
- label = label.upcase unless noupcase
103
- label = label.gsub(' // ', '\n')
104
- label
105
- end
106
- end
107
-
108
- class MemeBlockMacroProcessor < Extensions::DiagramBlockMacroProcessor
109
- include Meme
6
+ class MemeBlockMacroProcessor < DiagramBlockMacroProcessor
7
+ use_converter MemeConverter
110
8
 
111
9
  class StringReader
112
10
  def initialize(str)
@@ -123,7 +21,7 @@ module Asciidoctor
123
21
  def create_source(parent, target, attributes)
124
22
  attributes = attributes.dup
125
23
  attributes['background'] = apply_target_subs(parent, target)
126
- ::Asciidoctor::Diagram::Extensions::ReaderSource.new(parent, StringReader.new(''), attributes)
24
+ ::Asciidoctor::Diagram::ReaderSource.new(self, parent, StringReader.new(''), attributes)
127
25
  end
128
26
  end
129
27
  end