asciidoctor-diagram 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.adoc +262 -7
  3. data/README.adoc +463 -40
  4. data/README_zh-CN.adoc +336 -0
  5. data/Rakefile +3 -7
  6. data/examples/features.adoc +2 -2
  7. data/images/asciidoctor-diagram-classes.png +0 -0
  8. data/images/asciidoctor-diagram-process.png +0 -0
  9. data/lib/asciidoctor-diagram/a2s/converter.rb +55 -0
  10. data/lib/asciidoctor-diagram/a2s/extension.rb +14 -0
  11. data/lib/asciidoctor-diagram/a2s.rb +7 -0
  12. data/lib/asciidoctor-diagram/blockdiag/converter.rb +37 -0
  13. data/lib/asciidoctor-diagram/blockdiag/extension.rb +11 -11
  14. data/lib/asciidoctor-diagram/blockdiag.rb +5 -4
  15. data/lib/asciidoctor-diagram/bpmn/converter.rb +62 -0
  16. data/lib/asciidoctor-diagram/bpmn/extension.rb +14 -0
  17. data/lib/asciidoctor-diagram/bpmn.rb +7 -0
  18. data/lib/asciidoctor-diagram/diagram_converter.rb +19 -0
  19. data/lib/asciidoctor-diagram/diagram_processor.rb +320 -0
  20. data/lib/asciidoctor-diagram/diagram_source.rb +275 -0
  21. data/lib/asciidoctor-diagram/ditaa/converter.rb +86 -0
  22. data/lib/asciidoctor-diagram/ditaa/extension.rb +6 -28
  23. data/lib/asciidoctor-diagram/ditaa.rb +3 -4
  24. data/lib/asciidoctor-diagram/erd/converter.rb +31 -0
  25. data/lib/asciidoctor-diagram/erd/extension.rb +14 -0
  26. data/lib/asciidoctor-diagram/erd.rb +7 -0
  27. data/lib/asciidoctor-diagram/gnuplot/converter.rb +63 -0
  28. data/lib/asciidoctor-diagram/gnuplot/extension.rb +14 -0
  29. data/lib/asciidoctor-diagram/gnuplot.rb +7 -0
  30. data/lib/asciidoctor-diagram/graphviz/converter.rb +32 -0
  31. data/lib/asciidoctor-diagram/graphviz/extension.rb +8 -10
  32. data/lib/asciidoctor-diagram/graphviz.rb +3 -4
  33. data/lib/asciidoctor-diagram/http/server.rb +127 -0
  34. data/lib/asciidoctor-diagram/lilypond/converter.rb +54 -0
  35. data/lib/asciidoctor-diagram/lilypond/extension.rb +14 -0
  36. data/lib/asciidoctor-diagram/lilypond.rb +7 -0
  37. data/lib/asciidoctor-diagram/meme/converter.rb +122 -0
  38. data/lib/asciidoctor-diagram/meme/extension.rb +28 -0
  39. data/lib/asciidoctor-diagram/meme.rb +6 -0
  40. data/lib/asciidoctor-diagram/mermaid/converter.rb +178 -0
  41. data/lib/asciidoctor-diagram/mermaid/extension.rb +14 -0
  42. data/lib/asciidoctor-diagram/mermaid.rb +7 -0
  43. data/lib/asciidoctor-diagram/msc/converter.rb +35 -0
  44. data/lib/asciidoctor-diagram/msc/extension.rb +14 -0
  45. data/lib/asciidoctor-diagram/msc.rb +7 -0
  46. data/lib/asciidoctor-diagram/nomnoml/converter.rb +25 -0
  47. data/lib/asciidoctor-diagram/nomnoml/extension.rb +14 -0
  48. data/lib/asciidoctor-diagram/nomnoml.rb +7 -0
  49. data/lib/asciidoctor-diagram/plantuml/converter.rb +115 -0
  50. data/lib/asciidoctor-diagram/plantuml/extension.rb +14 -20
  51. data/lib/asciidoctor-diagram/plantuml.rb +3 -5
  52. data/lib/asciidoctor-diagram/salt.rb +7 -0
  53. data/lib/asciidoctor-diagram/shaape/converter.rb +25 -0
  54. data/lib/asciidoctor-diagram/shaape/extension.rb +9 -11
  55. data/lib/asciidoctor-diagram/shaape.rb +3 -5
  56. data/lib/asciidoctor-diagram/smcat/converter.rb +44 -0
  57. data/lib/asciidoctor-diagram/smcat/extension.rb +14 -0
  58. data/lib/asciidoctor-diagram/smcat.rb +7 -0
  59. data/lib/asciidoctor-diagram/svgbob/converter.rb +25 -0
  60. data/lib/asciidoctor-diagram/svgbob/extension.rb +14 -0
  61. data/lib/asciidoctor-diagram/svgbob.rb +7 -0
  62. data/lib/asciidoctor-diagram/syntrax/converter.rb +55 -0
  63. data/lib/asciidoctor-diagram/syntrax/extension.rb +14 -0
  64. data/lib/asciidoctor-diagram/syntrax.rb +7 -0
  65. data/lib/asciidoctor-diagram/tikz/converter.rb +56 -0
  66. data/lib/asciidoctor-diagram/tikz/extension.rb +14 -0
  67. data/lib/asciidoctor-diagram/tikz.rb +7 -0
  68. data/lib/asciidoctor-diagram/umlet/converter.rb +24 -0
  69. data/lib/asciidoctor-diagram/umlet/extension.rb +14 -0
  70. data/lib/asciidoctor-diagram/umlet.rb +7 -0
  71. data/lib/asciidoctor-diagram/util/binaryio.rb +20 -0
  72. data/lib/asciidoctor-diagram/util/cli.rb +81 -0
  73. data/lib/asciidoctor-diagram/util/cli_generator.rb +73 -22
  74. data/lib/asciidoctor-diagram/util/gif.rb +21 -0
  75. data/lib/asciidoctor-diagram/util/java.rb +95 -1
  76. data/lib/asciidoctor-diagram/util/java_jruby.rb +14 -20
  77. data/lib/asciidoctor-diagram/util/java_socket.rb +175 -0
  78. data/lib/asciidoctor-diagram/util/pdf.rb +10 -0
  79. data/lib/asciidoctor-diagram/util/platform.rb +97 -0
  80. data/lib/asciidoctor-diagram/util/png.rb +1 -0
  81. data/lib/asciidoctor-diagram/util/svg.rb +4 -3
  82. data/lib/asciidoctor-diagram/util/which.rb +15 -9
  83. data/lib/asciidoctor-diagram/vega/converter.rb +47 -0
  84. data/lib/asciidoctor-diagram/vega/extension.rb +14 -0
  85. data/lib/asciidoctor-diagram/vega.rb +10 -0
  86. data/lib/asciidoctor-diagram/version.rb +1 -1
  87. data/lib/asciidoctor-diagram/wavedrom/converter.rb +50 -0
  88. data/lib/asciidoctor-diagram/wavedrom/extension.rb +14 -0
  89. data/lib/asciidoctor-diagram/wavedrom.rb +7 -0
  90. data/lib/asciidoctor-diagram.rb +22 -5
  91. data/lib/batik-all-1.10.jar +0 -0
  92. data/lib/ditaa-1.3.14.jar +0 -0
  93. data/lib/ditaamini-0.12.jar +0 -0
  94. data/lib/jlatexmath-minimal-1.0.5.jar +0 -0
  95. data/lib/plantuml-1.3.14.jar +0 -0
  96. data/lib/plantuml.jar +0 -0
  97. data/lib/server-1.3.14.jar +0 -0
  98. data/spec/a2s_spec.rb +167 -0
  99. data/spec/blockdiag_spec.rb +55 -24
  100. data/spec/bpmn-example.xml +44 -0
  101. data/spec/bpmn_spec.rb +96 -0
  102. data/spec/ditaa_spec.rb +150 -15
  103. data/spec/erd_spec.rb +289 -0
  104. data/spec/gnuplot_spec.rb +478 -0
  105. data/spec/graphviz_spec.rb +20 -20
  106. data/spec/lilypond_spec.rb +151 -0
  107. data/spec/man.jpg +0 -0
  108. data/spec/meme_spec.rb +67 -0
  109. data/spec/mermaid_spec.rb +336 -0
  110. data/spec/msc_spec.rb +230 -0
  111. data/spec/nomnoml_spec.rb +170 -0
  112. data/spec/plantuml_spec.rb +895 -54
  113. data/spec/shaape_spec.rb +25 -24
  114. data/spec/smcat_spec.rb +164 -0
  115. data/spec/svgbob_spec.rb +167 -0
  116. data/spec/syntrax_spec.rb +228 -0
  117. data/spec/test_helper.rb +88 -9
  118. data/spec/tikz_spec.rb +127 -0
  119. data/spec/umlet_spec.rb +85 -0
  120. data/spec/vega_spec.rb +241 -0
  121. data/spec/wavedrom_spec.rb +214 -0
  122. metadata +130 -35
  123. data/lib/asciidoctor-diagram/plantuml/generator.rb +0 -46
  124. data/lib/asciidoctor-diagram/util/diagram.rb +0 -220
  125. data/lib/asciidoctor-diagram/util/java_rjb.rb +0 -90
  126. data/lib/ditaamini0_9.jar +0 -0
@@ -0,0 +1,55 @@
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 SyntraxConverter
9
+ include DiagramConverter
10
+ include CliGenerator
11
+
12
+
13
+ def supported_formats
14
+ [:png, :svg]
15
+ end
16
+
17
+ def collect_options(source, name)
18
+ {
19
+ :heading => source.attr('heading', nil, name),
20
+ :scale => source.attr('scale', nil, name),
21
+ :transparent => source.attr('transparent', nil, name),
22
+ :style => source.attr('style', nil, name)
23
+ }
24
+ end
25
+
26
+
27
+ def convert(source, format, options)
28
+ generate_file(source.find_command('syntrax'), 'spec', format.to_s, source.to_s) do |tool_path, input_path, output_path|
29
+ args = [tool_path, '-i', Platform.native_path(input_path), '-o', Platform.native_path(output_path)]
30
+
31
+ title = options[:heading]
32
+ if title
33
+ args << '--title' << title
34
+ end
35
+
36
+ scale = options[:scale]
37
+ if scale
38
+ args << '--scale' << scale
39
+ end
40
+
41
+ transparent = options[:transparent]
42
+ if transparent == 'true'
43
+ args << '--transparent'
44
+ end
45
+ style = options[:style]
46
+ if style
47
+ args << '--style' << style
48
+ end
49
+
50
+ args
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../diagram_processor'
2
+ require_relative 'converter'
3
+
4
+ module Asciidoctor
5
+ module Diagram
6
+ class SyntraxBlockProcessor < DiagramBlockProcessor
7
+ use_converter SyntraxConverter
8
+ end
9
+
10
+ class SyntraxBlockMacroProcessor < DiagramBlockMacroProcessor
11
+ use_converter SyntraxConverter
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ require 'asciidoctor/extensions'
2
+ require_relative 'syntrax/extension'
3
+
4
+ Asciidoctor::Extensions.register do
5
+ block Asciidoctor::Diagram::SyntraxBlockProcessor, :syntrax
6
+ block_macro Asciidoctor::Diagram::SyntraxBlockMacroProcessor, :syntrax
7
+ end
@@ -0,0 +1,56 @@
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 TikZConverter
9
+ include DiagramConverter
10
+ include CliGenerator
11
+
12
+ def supported_formats
13
+ [:pdf, :svg]
14
+ end
15
+
16
+
17
+ def convert(source, format, options)
18
+ latexpath = source.find_command('pdflatex')
19
+
20
+ if format == :svg
21
+ svgpath = source.find_command('pdf2svg')
22
+ else
23
+ svgpath = nil
24
+ end
25
+
26
+ latex = <<'END'
27
+ \documentclass[border=2bp, tikz]{standalone}
28
+ \usepackage{tikz}
29
+ \begin{document}
30
+ \begingroup
31
+ \tikzset{every picture/.style={scale=1}}
32
+ END
33
+ latex << source.to_s
34
+ latex << <<'END'
35
+ \endgroup
36
+ \end{document}
37
+ END
38
+
39
+ pdf = generate_file(latexpath, 'tex', 'pdf', latex) do |tool_path, input_path, output_path|
40
+ {
41
+ :args => [tool_path, '-shell-escape', '-file-line-error', '-interaction=nonstopmode', '-output-directory', Platform.native_path(File.dirname(output_path)), Platform.native_path(input_path)],
42
+ :out_file => "#{File.dirname(input_path)}/#{File.basename(input_path, '.*')}.pdf"
43
+ }
44
+ end
45
+
46
+ if svgpath
47
+ generate_file(svgpath, 'pdf', 'svg', pdf) do |tool_path, input_path, output_path|
48
+ [tool_path, Platform.native_path(input_path), Platform.native_path(output_path)]
49
+ end
50
+ else
51
+ pdf
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../diagram_processor'
2
+ require_relative 'converter'
3
+
4
+ module Asciidoctor
5
+ module Diagram
6
+ class TikZBlockProcessor < DiagramBlockProcessor
7
+ use_converter TikZConverter
8
+ end
9
+
10
+ class TikZBlockMacroProcessor < DiagramBlockMacroProcessor
11
+ use_converter TikZConverter
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ require 'asciidoctor/extensions'
2
+ require_relative 'tikz/extension'
3
+
4
+ Asciidoctor::Extensions.register do
5
+ block Asciidoctor::Diagram::TikZBlockProcessor, :tikz
6
+ block_macro Asciidoctor::Diagram::TikZBlockMacroProcessor, :tikz
7
+ end
@@ -0,0 +1,24 @@
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 UmletConverter
9
+ include DiagramConverter
10
+ include CliGenerator
11
+
12
+
13
+ def supported_formats
14
+ [:svg, :png, :pdf, :gif]
15
+ end
16
+
17
+ def convert(source, format, options)
18
+ generate_file(source.find_command('umlet'), 'uxf', format.to_s, source.to_s) do |tool_path, input_path, output_path|
19
+ [tool_path, '-action=convert', "-format=#{format.to_s}", "-filename=#{Platform.native_path(input_path)}", "-output=#{Platform.native_path(output_path)}"]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../diagram_processor'
2
+ require_relative 'converter'
3
+
4
+ module Asciidoctor
5
+ module Diagram
6
+ class UmletBlockProcessor < DiagramBlockProcessor
7
+ use_converter UmletConverter
8
+ end
9
+
10
+ class UmletBlockMacroProcessor < DiagramBlockMacroProcessor
11
+ use_converter UmletConverter
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ require 'asciidoctor/extensions'
2
+ require_relative 'umlet/extension'
3
+
4
+ Asciidoctor::Extensions.register do
5
+ block Asciidoctor::Diagram::UmletBlockProcessor, :umlet
6
+ block_macro Asciidoctor::Diagram::UmletBlockMacroProcessor, :umlet
7
+ end
@@ -1,17 +1,37 @@
1
1
  module Asciidoctor
2
2
  module Diagram
3
+ # Helper class to read binary values from a String
4
+ # @private
3
5
  class BinaryIO
4
6
  def initialize(string)
5
7
  @data = string
6
8
  @offset = 0
7
9
  end
8
10
 
11
+ def read_uint16_be
12
+ uint16 = @data[@offset,2].unpack('n')[0]
13
+ @offset += 2
14
+ uint16
15
+ end
16
+
17
+ def read_uint16_le
18
+ uint16 = @data[@offset,2].unpack('v')[0]
19
+ @offset += 2
20
+ uint16
21
+ end
22
+
9
23
  def read_uint32_be
10
24
  uint32 = @data[@offset,4].unpack('N')[0]
11
25
  @offset += 4
12
26
  uint32
13
27
  end
14
28
 
29
+ def read_uint32_le
30
+ uint32 = @data[@offset,4].unpack('V')[0]
31
+ @offset += 4
32
+ uint32
33
+ end
34
+
15
35
  def read_string(length, encoding = Encoding::ASCII_8BIT)
16
36
  str = @data[@offset,length]
17
37
  @offset += length
@@ -0,0 +1,81 @@
1
+ module Asciidoctor
2
+ module Diagram
3
+ # @private
4
+ module Cli
5
+ if RUBY_PLATFORM == "java"
6
+ # Workaround for https://github.com/jruby/jruby/issues/5565
7
+ # Kernel.spawn (and as a consequence Open3.capture3 which uses it)
8
+ # is not reliable on all versions of JRuby.
9
+ require_relative 'java'
10
+
11
+ def self.run(*args)
12
+ opts = args.pop if args.last.is_a? Hash
13
+ in_data = opts && opts[:stdin_data]
14
+
15
+ pb = java.lang.ProcessBuilder.new(*args)
16
+ p = pb.start
17
+
18
+ stdout = ""
19
+ out_reader = start_stream_reader(p.getInputStream, stdout)
20
+ stderr = ""
21
+ err_reader = start_stream_reader(p.getErrorStream, stderr)
22
+
23
+ if in_data
24
+ p.getOutputStream.write(in_data.to_java_bytes)
25
+ p.getOutputStream.close
26
+ end
27
+
28
+ p.waitFor
29
+
30
+ out_reader.join
31
+ err_reader.join
32
+
33
+ status = p.exitValue
34
+
35
+ if status != 0
36
+ raise "#{File.basename(args[0])} failed: #{stdout.empty? ? stderr : stdout}"
37
+ end
38
+
39
+ {
40
+ :out => stdout,
41
+ :err => stderr,
42
+ :status => status
43
+ }
44
+ end
45
+
46
+ private
47
+ def self.start_stream_reader(in_stream, out_string)
48
+ Thread.new {
49
+ buffer = ::Java::byte[4096].new
50
+ while (bytes_read = in_stream.read(buffer)) != -1
51
+ if bytes_read < buffer.length
52
+ str = String.from_java_bytes(java.util.Arrays.copyOf(buffer, bytes_read))
53
+ else
54
+ str = String.from_java_bytes(buffer)
55
+ end
56
+ out_string << str
57
+ end
58
+ }
59
+ end
60
+ else
61
+ require 'open3'
62
+
63
+ def self.run(*args)
64
+ stdout, stderr, status = Open3.capture3(*args)
65
+
66
+ exit = status.exitstatus
67
+
68
+ if exit != 0
69
+ raise "#{File.basename(args[0])} failed: #{stdout.empty? ? stderr : stdout}"
70
+ end
71
+
72
+ {
73
+ :out => stdout,
74
+ :err => stderr,
75
+ :status => exit
76
+ }
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,38 +1,89 @@
1
1
  require 'tempfile'
2
-
3
- require_relative '../util/java'
4
- require_relative '../util/which'
2
+ require_relative 'cli'
5
3
 
6
4
  module Asciidoctor
7
5
  module Diagram
6
+ # @private
8
7
  module CliGenerator
9
- def self.generate(tool, parent, code)
10
- tool_var = '@' + tool
11
-
12
- tool_path = instance_variable_get(tool_var)
13
- unless tool_path
14
- tool_path = parent.document.attributes[tool]
15
- tool_path = ::Asciidoctor::Diagram.which(tool) unless tool_path && File.executable?(tool_path)
16
- raise "Could not find the '#{tool}' executable in PATH; add it to the PATH or specify its location using the 'shaape' document attribute" unless tool_path
17
- instance_variable_set(tool_var, tool_path)
18
- end
8
+ def generate_stdin(tool, format, code)
9
+ tool_name = File.basename(tool)
19
10
 
20
- target_file = Tempfile.new(tool)
11
+ target_file = Tempfile.new([tool_name, ".#{format}"])
21
12
  begin
22
13
  target_file.close
23
14
 
24
- args = yield tool_path, target_file.path
15
+ opts = yield tool, target_file.path
25
16
 
26
- IO.popen(args, "w") do |io|
27
- io.write code
28
- end
29
- result_code = $?
17
+ generate(opts, target_file.path, :stdin_data => code)
18
+ ensure
19
+ target_file.unlink
20
+ end
21
+ end
30
22
 
31
- raise "#{tool} image generation failed" unless result_code == 0
23
+ def generate_stdin_stdout(tool, code)
24
+ if block_given?
25
+ opts = yield tool
26
+ else
27
+ opts = [tool]
28
+ end
29
+ generate(opts, :stdout, :stdin_data => code)
30
+ end
31
+
32
+ def generate_file(tool, input_ext, output_ext, code)
33
+ tool_name = File.basename(tool)
34
+
35
+ source_file = Tempfile.new([tool_name, ".#{input_ext}"])
36
+ begin
37
+ File.write(source_file.path, code)
32
38
 
33
- File.read(target_file.path)
39
+ target_file = Tempfile.new([tool_name, ".#{output_ext}"])
40
+ begin
41
+ target_file.close
42
+
43
+ opts = yield tool, source_file.path, target_file.path
44
+
45
+ generate(opts, target_file.path)
46
+ ensure
47
+ target_file.unlink
48
+ end
34
49
  ensure
35
- target_file.unlink
50
+ source_file.unlink
51
+ end
52
+ end
53
+
54
+ private
55
+ def generate(opts, target_file, open3_opts = {})
56
+ case opts
57
+ when Array
58
+ args = opts
59
+ out_file = nil
60
+ when Hash
61
+ args = opts[:args]
62
+ out_file = opts[:out_file]
63
+ else
64
+ raise "Block passed to generate_file should return an Array or a Hash"
65
+ end
66
+
67
+ result = ::Asciidoctor::Diagram::Cli.run(*args, open3_opts)
68
+
69
+ data = target_file == :stdout ? result[:out] : read_result(target_file, out_file)
70
+
71
+ if data.empty?
72
+ raise "#{args[0]} failed: #{result[:out].empty? ? result[:err] : result[:out]}"
73
+ end
74
+
75
+ data
76
+ end
77
+
78
+ def read_result(target_file, out_file = nil)
79
+ if File.exist?(out_file || target_file)
80
+ if out_file
81
+ File.rename(out_file, target_file)
82
+ end
83
+
84
+ File.binread(target_file)
85
+ else
86
+ ''
36
87
  end
37
88
  end
38
89
  end
@@ -0,0 +1,21 @@
1
+ require_relative 'binaryio'
2
+
3
+ module Asciidoctor
4
+ module Diagram
5
+ # @private
6
+ module GIF
7
+ GIF87A_SIGNATURE = 'GIF87a'.force_encoding(Encoding::ASCII_8BIT)
8
+ GIF89A_SIGNATURE = 'GIF89a'.force_encoding(Encoding::ASCII_8BIT)
9
+
10
+ def self.get_image_size(data)
11
+ bio = BinaryIO.new(data)
12
+ gif_signature = bio.read_string(6)
13
+ raise "Invalid GIF signature" unless gif_signature == GIF87A_SIGNATURE || gif_signature == GIF89A_SIGNATURE
14
+
15
+ width = bio.read_uint16_le
16
+ height = bio.read_uint16_le
17
+ [width, height]
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,99 @@
1
+ require 'json'
2
+
3
+ module Asciidoctor
4
+ module Diagram
5
+ # @private
6
+ module Java
7
+ def self.classpath
8
+ @classpath ||= [
9
+ File.expand_path(File.join('../..', 'server-1.3.14.jar'), File.dirname(__FILE__))
10
+ ]
11
+ end
12
+
13
+ CRLF = "\r\n".encode(Encoding::US_ASCII)
14
+
15
+ def self.format_request(req, io)
16
+ io.set_encoding Encoding::US_ASCII
17
+ io.write "POST #{req[:url]} HTTP/1.1"
18
+ io.write CRLF
19
+
20
+ headers = req[:headers]
21
+ if headers
22
+ headers.each_pair do |key, value|
23
+ io.write "#{key}: #{value}"
24
+ io.write CRLF
25
+ end
26
+ end
27
+
28
+ if req[:body]
29
+ unless headers && headers['Content-Length']
30
+ io.write 'Content-Length: '
31
+ io.write req[:body].bytesize.to_s
32
+ io.write CRLF
33
+ end
34
+
35
+ unless headers && headers['Content-Type']
36
+ io.write 'Content-Type: text/plain; charset='
37
+ io.write req[:body].encoding.name
38
+ io.write CRLF
39
+ end
40
+ end
41
+
42
+ io.write CRLF
43
+
44
+ io.set_encoding Encoding::BINARY
45
+ io.write req[:body]
46
+ end
47
+
48
+ STATUS_LINE = Regexp.new("HTTP/1.1 (\\d+) (.*)\r\n".encode(Encoding::US_ASCII))
49
+
50
+ def self.parse_response(io)
51
+ resp = {}
52
+
53
+ io.set_encoding Encoding::US_ASCII
54
+ status_line = io.readline(CRLF)
55
+ status_line_parts = STATUS_LINE.match status_line
56
+ resp[:code] = status_line_parts[1].to_i
57
+ resp[:reason] = status_line_parts[2]
58
+
59
+ headers = {}
60
+ until (header = io.readline(CRLF).strip).empty?
61
+ key, value = header.split ':', 2
62
+ headers[key] = value.strip
63
+ end
64
+
65
+ resp[:headers] = headers
66
+
67
+ content_length = headers['Content-Length']
68
+ if content_length
69
+ io.set_encoding Encoding::BINARY
70
+ resp[:body] = io.read(content_length.to_i)
71
+ end
72
+
73
+ resp
74
+ end
75
+
76
+ def self.create_error(prefix_msg, response)
77
+ content_type = response[:headers]['Content-Type'] || 'text/plain'
78
+ if content_type.start_with? 'application/json'
79
+ json = JSON.parse(response[:body].force_encoding(Encoding::UTF_8))
80
+ ruby_bt = Kernel.caller(2)
81
+ java_bt = json['stk'].map { |java_line| "#{java_line[0]}:#{java_line[3]}: in '#{java_line[2]}'" }
82
+ error = RuntimeError.new("#{prefix_msg}: #{json['msg']}")
83
+ error.set_backtrace java_bt + ruby_bt
84
+ raise error
85
+ elsif content_type.start_with? 'text/plain'
86
+ raise "#{prefix_msg}: #{response[:reason]} #{response[:body].force_encoding(Encoding::UTF_8)}"
87
+ else
88
+ raise "#{prefix_msg}: #{response[:reason]}"
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+
1
95
  if RUBY_PLATFORM == "java"
2
96
  require_relative 'java_jruby'
3
97
  else
4
- require_relative 'java_rjb'
98
+ require_relative 'java_socket'
5
99
  end
@@ -1,39 +1,33 @@
1
1
  require 'java'
2
+ require 'stringio'
2
3
 
3
4
  module Asciidoctor
4
5
  module Diagram
6
+ # @private
5
7
  module Java
6
- def self.classpath
7
- @classpath ||= []
8
- end
9
-
10
8
  def self.load
11
- if @loaded
9
+ if defined?(@loaded) && @loaded
12
10
  return
13
11
  end
14
12
 
15
- classpath.each { |j| require j }
13
+ classpath.flatten.each { |j| require j }
16
14
  @loaded = true
17
15
  end
18
16
 
19
- def self.array_to_java_array(array, type)
20
- array.to_java(type)
21
- end
17
+ def self.send_request(req)
18
+ cp = ::Java.org.asciidoctor.diagram.CommandProcessor.new()
22
19
 
23
- def self.string_from_java_bytes(bytes)
24
- String.from_java_bytes(bytes)
25
- end
20
+ req_io = StringIO.new
21
+ format_request(req, req_io)
22
+ req_io.close
26
23
 
27
- def self.method_missing(meth, *args, &block)
28
- raise "No arguments expected" unless args.empty?
29
- raise "No block expected" if block
24
+ response = cp.processRequest(req_io.string.to_java_bytes)
30
25
 
31
- load
32
- ::Java.send(meth)
33
- end
26
+ resp_io = StringIO.new(String.from_java_bytes(response))
27
+ resp = parse_response(resp_io)
28
+ resp_io.close
34
29
 
35
- def self.new_object(java_class, signature = nil, *args)
36
- java_class.new(*args)
30
+ resp
37
31
  end
38
32
  end
39
33
  end