asciidoctor-diagram 1.5.19 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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