asciidoctor-diagram 2.0.5 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +17 -2
  3. data/README.adoc +25 -516
  4. data/Rakefile +1 -1
  5. data/docs/antora.yml +3 -0
  6. data/{images → docs/modules/ROOT/images}/asciidoctor-diagram-classes.png +0 -0
  7. data/docs/modules/ROOT/images/asciidoctor-diagram-process.png +0 -0
  8. data/docs/modules/ROOT/pages/index.adoc +21 -0
  9. data/docs/modules/ROOT/partials/advanced.adoc +303 -0
  10. data/docs/modules/ROOT/partials/create_diagram.adoc +131 -0
  11. data/docs/modules/ROOT/partials/generate.adoc +15 -0
  12. data/docs/modules/ROOT/partials/installation.adoc +19 -0
  13. data/docs/modules/ROOT/partials/uris.adoc +38 -0
  14. data/examples/features.adoc +1 -1
  15. data/lib/asciidoctor-diagram/diagram_processor.rb +2 -1
  16. data/lib/asciidoctor-diagram/ditaa/converter.rb +14 -5
  17. data/lib/asciidoctor-diagram/ditaa/ditaa-1.3.17.jar +0 -0
  18. data/lib/asciidoctor-diagram/http/converter.rb +1 -7
  19. data/lib/asciidoctor-diagram/lilypond/converter.rb +11 -1
  20. data/lib/asciidoctor-diagram/meme/converter.rb +15 -9
  21. data/lib/asciidoctor-diagram/mermaid/converter.rb +27 -10
  22. data/lib/asciidoctor-diagram/pikchr/converter.rb +8 -1
  23. data/lib/asciidoctor-diagram/plantuml/converter.rb +15 -9
  24. data/lib/asciidoctor-diagram/plantuml/plantuml-1.3.17.jar +0 -0
  25. data/lib/asciidoctor-diagram/svgbob/converter.rb +4 -0
  26. data/lib/asciidoctor-diagram/util/cli.rb +16 -1
  27. data/lib/asciidoctor-diagram/util/cli_generator.rb +4 -2
  28. data/lib/asciidoctor-diagram/util/gif.rb +1 -1
  29. data/lib/asciidoctor-diagram/util/java.rb +5 -3
  30. data/lib/asciidoctor-diagram/util/java_jruby.rb +4 -1
  31. data/lib/asciidoctor-diagram/util/java_socket.rb +10 -1
  32. data/lib/asciidoctor-diagram/util/pdf.rb +1 -1
  33. data/lib/asciidoctor-diagram/util/png.rb +1 -1
  34. data/lib/asciidoctor-diagram/util/server-1.3.17.jar +0 -0
  35. data/lib/asciidoctor-diagram/util/svg.rb +25 -4
  36. data/lib/asciidoctor-diagram/version.rb +1 -1
  37. data/spec/a2s_spec.rb +3 -3
  38. data/spec/blockdiag_spec.rb +3 -3
  39. data/spec/bytefield_spec.rb +3 -3
  40. data/spec/ditaa_spec.rb +1 -1
  41. data/spec/dpic_spec.rb +3 -3
  42. data/spec/erd_spec.rb +5 -5
  43. data/spec/lilypond_spec.rb +3 -3
  44. data/spec/mermaid_spec.rb +37 -0
  45. data/spec/pikchr_spec.rb +21 -3
  46. data/spec/shaape_spec.rb +3 -3
  47. data/spec/svgbob_spec.rb +3 -3
  48. data/spec/syntrax_spec.rb +3 -3
  49. data/spec/test_helper.rb +3 -7
  50. data/spec/tikz_spec.rb +3 -3
  51. metadata +57 -13
  52. data/README_zh-CN.adoc +0 -336
  53. data/images/asciidoctor-diagram-process.png +0 -0
  54. data/lib/batik-all-1.10.jar +0 -0
  55. data/lib/ditaa-1.3.15.jar +0 -0
  56. data/lib/ditaamini-0.12.jar +0 -0
  57. data/lib/jlatexmath-minimal-1.0.5.jar +0 -0
  58. data/lib/plantuml-1.3.15.jar +0 -0
  59. data/lib/plantuml.jar +0 -0
  60. data/lib/server-1.3.15.jar +0 -0
@@ -0,0 +1,15 @@
1
+ == Generating a Diagram from a Terminal
2
+
3
+ You can load Asciidoctor diagram in a terminal using the `-r` flag.
4
+
5
+ $ asciidoctor -r asciidoctor-diagram sample.adoc
6
+
7
+ You can also use Asciidoctor diagram with other converters, such as Asciidoctor EPUB.
8
+ Asciidoctor-epub3 is also loaded with the `-r` flag.
9
+
10
+ $ asciidoctor -r asciidoctor-diagram -r asciidoctor-epub3 -b epub3 sample.adoc
11
+
12
+ Or, you can invoke Asciidoctor and the EPUB converter with the `asciidoctor-epub3` command.
13
+ The command implicitly sets the `-r` and `-b` flags for EPUB3 output.
14
+
15
+ $ asciidoctor-epub3 -r asciidoctor-diagram sample.adoc
@@ -0,0 +1,19 @@
1
+ == Installation
2
+
3
+ Asciidoctor Diagram is a RubyGem, which can be installed using the `gem` or `bundle` commands.
4
+
5
+ You can install the Asciidoctor Diagram gem by typing `gem install` in the CLI.
6
+
7
+ $ gem install asciidoctor-diagram
8
+
9
+ by first adding the following entry to your project's [.path]_Gemfile_.
10
+
11
+ .Gemfile
12
+ [source,ruby]
13
+ ----
14
+ gem 'asciidoctor-diagram'
15
+ ----
16
+
17
+ Then execute `bundle` in the CLI.
18
+
19
+ $ bundle
@@ -0,0 +1,38 @@
1
+ :uri-a2s: https://github.com/dhobsd/asciitosvg
2
+ :uri-actdiag: http://blockdiag.com/en/actdiag/index.html
3
+ :uri-asciidoctor-api: http://asciidoctor.org/docs/user-manual/#api
4
+ :uri-asciidoctor-extensions: http://asciidoctor.org/docs/user-manual/#extension-points
5
+ :uri-blockdiag: http://blockdiag.com
6
+ :uri-bpmn: https://github.com/gtudan/bpmn-js-cmd
7
+ :uri-bytefield: https://github.com/Deep-Symmetry/bytefield-svg
8
+ :uri-ditaa: http://ditaa.sourceforge.net/
9
+ :uri-dpic: https://gitlab.com/aplevich/dpic
10
+ :uri-dot: https://graphviz.gitlab.io/_pages/doc/info/lang.html
11
+ :uri-erd: https://github.com/BurntSushi/erd
12
+ :uri-gnuplot: http://gnuplot.info
13
+ :uri-graphviz: https://graphviz.gitlab.io
14
+ :uri-imagemagick: http://www.imagemagick.org
15
+ :uri-java: http://java.sun.com
16
+ :uri-mermaid: https://github.com/mermaid-js/mermaid-cli
17
+ :uri-mscgen: http://www.mcternan.me.uk/mscgen/
18
+ :uri-nomnoml: http://nomnoml.com
19
+ :uri-nwdiag: http://blockdiag.com/en/nwdiag/index.html
20
+ :uri-packetdiag: http://blockdiag.com/en/nwdiag/index.html
21
+ :uri-phantomjs: http://phantomjs.org
22
+ :uri-pikchr: https://pikchr.org
23
+ :uri-plantuml: http://plantuml.sourceforge.net
24
+ :uri-py-plantuml: https://code.google.com/p/asciidoc-plantuml/
25
+ :uri-rackdiag: http://blockdiag.com/en/nwdiag/index.html
26
+ :uri-seqdiag: http://blockdiag.com/en/seqdiag/index.html
27
+ :uri-shaape: https://github.com/christiangoltz/shaape
28
+ :uri-smcat: https://github.com/sverweij/state-machine-cat
29
+ :uri-svgbob: https://github.com/ivanceras/svgbobrus
30
+ :uri-symbolator: https://github.com/kevinpt/symbolator
31
+ :uri-syntrax: https://kevinpt.github.io/syntrax/
32
+ :uri-tikz: https://github.com/pgf-tikz/pgf
33
+ :uri-umlet: http://www.umlet.com/
34
+ :uri-vega: https://vega.github.io/vega/
35
+ :uri-vegalite: https://vega.github.io/vega-lite/
36
+ :uri-wavedrom: http://wavedrom.com
37
+ :uri-wavedromeditor: https://github.com/wavedrom/wavedrom.github.io/releases
38
+ :uri-wavedromcli: https://github.com/wavedrom/cli
@@ -150,7 +150,7 @@ results in a block with the correct caption and id applied to it.
150
150
  Asciidoctor-diagram also supports the various diagram block in block macro form.
151
151
  These are macros of the form `<name>::<target>[<attrlist>]`.
152
152
 
153
- In asciidoctor-diagram the macro names are identical to the block styles: `ditaa`, `graphivz` and `plantuml`
153
+ In asciidoctor-diagram the macro names are identical to the block styles: `ditaa`, `graphviz` and `plantuml`
154
154
  The target is the path to the file containing the diagram source code.
155
155
  When the target is a relative path it is resolved with respect to the location of the document being processed.
156
156
  The attribute list behaves mostly the same as with the block styles.
@@ -174,7 +174,8 @@ module Asciidoctor
174
174
  metadata = source.create_image_metadata
175
175
  metadata[:options] = options
176
176
 
177
- result, metadata[:width], metadata[:height] = params[:decoder].post_process_image(result)
177
+ allow_image_optimisation = source.attr('optimise', 'true') == 'true'
178
+ result, metadata[:width], metadata[:height] = params[:decoder].post_process_image(result, allow_image_optimisation)
178
179
 
179
180
  FileUtils.mkdir_p(File.dirname(image_file)) unless Dir.exist?(File.dirname(image_file))
180
181
  File.open(image_file, 'wb') {|f| f.write result}
@@ -23,11 +23,20 @@ module Asciidoctor
23
23
  :transparent => lambda { |o, v| o << '--transparent' if v == 'true'}
24
24
  }
25
25
 
26
- JARS = ['ditaa-1.3.15.jar', 'ditaamini-0.12.jar'].map do |jar|
27
- File.expand_path File.join('../..', jar), File.dirname(__FILE__)
28
- end
29
- Java.classpath.concat JARS
30
-
26
+ CLASSPATH_ENV = 'DIAGRAM_DITAA_CLASSPATH'
27
+ DITAA_JARS = if ENV.has_key?(CLASSPATH_ENV)
28
+ ENV[CLASSPATH_ENV].split(File::PATH_SEPARATOR)
29
+ else
30
+ begin
31
+ require 'asciidoctor-diagram/ditaa/classpath'
32
+ ::Asciidoctor::Diagram::DitaaClasspath::JAR_FILES
33
+ rescue LoadError
34
+ raise "Could not load PlantUML. Eiter require 'asciidoctor-diagram-ditaamini' or specify the location of the PlantUML JAR(s) using the 'DIAGRAM_DITAA_CLASSPATH' environment variable."
35
+ end
36
+ end
37
+
38
+ Java.classpath.concat Dir[File.join(File.dirname(__FILE__), '*.jar')]
39
+ Java.classpath.concat DITAA_JARS
31
40
 
32
41
  def supported_formats
33
42
  [:png, :svg]
@@ -23,12 +23,6 @@ module Asciidoctor
23
23
  @converter.supported_formats
24
24
  end
25
25
 
26
- def collect_options(source, name)
27
- {
28
- :block_name => name
29
- }
30
- end
31
-
32
26
  def convert(source, format, options)
33
27
  code = source.code
34
28
 
@@ -58,7 +52,7 @@ module Asciidoctor
58
52
 
59
53
  path = uri.path
60
54
  path << '/' unless path.end_with? '/'
61
- path << options[:block_name].to_s
55
+ path << source.diagram_type.to_s
62
56
  path << '/' << format.to_s
63
57
  path << '/' << data
64
58
  uri.path = path
@@ -9,6 +9,16 @@ module Asciidoctor
9
9
  include DiagramConverter
10
10
  include CliGenerator
11
11
 
12
+ EXTRA_PATH = []
13
+
14
+ if ::Asciidoctor::Diagram::Platform.os == :macosx
15
+ lilypond_app = ::Asciidoctor::Diagram::Which.which('LilyPond.app', :path => ['/Applications'])
16
+ if lilypond_app
17
+ EXTRA_PATH << File.join(lilypond_app, 'Contents/Resources/bin')
18
+ end
19
+ end
20
+
21
+ EXTRA_PATH.freeze
12
22
 
13
23
  def supported_formats
14
24
  [:png, :pdf]
@@ -34,7 +44,7 @@ module Asciidoctor
34
44
 
35
45
  resolution = options[:resolution]
36
46
 
37
- generate_stdin(source.find_command('lilypond'), format.to_s, code) do |tool_path, output_path|
47
+ generate_stdin(source.find_command('lilypond', :path => EXTRA_PATH), format.to_s, code) do |tool_path, output_path|
38
48
  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
49
 
40
50
  args << '-dsafe'
@@ -34,8 +34,16 @@ module Asciidoctor
34
34
  end
35
35
 
36
36
  def convert(source, format, options)
37
- convert = source.find_command('convert')
38
- identify = source.find_command('identify')
37
+ magick = source.find_command('magick', :raise_on_error => false)
38
+ if magick
39
+ convert = ->(*args) { Cli.run(magick, 'convert', *args) }
40
+ identify = ->(*args) { Cli.run(magick, 'identify', *args) }
41
+ else
42
+ convert_cmd = source.find_command('convert')
43
+ convert = ->(*args) { Cli.run(convert_cmd, *args) }
44
+ identify_cmd = source.find_command('identify')
45
+ identify = ->(*args) { Cli.run(identify_cmd, *args) }
46
+ end
39
47
 
40
48
  bg_img = options[:bg_img]
41
49
  raise "background attribute is required" unless bg_img
@@ -50,7 +58,7 @@ module Asciidoctor
50
58
  font = options[:font] || 'Impact'
51
59
  noupcase = options[:noupcase]
52
60
 
53
- dimensions = Cli.run(identify, '-format', '%w %h', bg_img)[:out].match(/(?<w>\d+) (?<h>\d+)/)
61
+ dimensions = identify.call('-format', '%w %h', bg_img)[:out].match(/(?<w>\d+) (?<h>\d+)/)
54
62
  bg_width = dimensions['w'].to_i
55
63
  bg_height = dimensions['h'].to_i
56
64
  label_width = bg_width
@@ -58,8 +66,7 @@ module Asciidoctor
58
66
 
59
67
  if top_label
60
68
  top_img = Tempfile.new(['meme', '.png'])
61
- Cli.run(
62
- convert,
69
+ convert.call(
63
70
  '-background', 'none',
64
71
  '-fill', fill_color,
65
72
  '-stroke', stroke_color,
@@ -76,8 +83,7 @@ module Asciidoctor
76
83
 
77
84
  if bottom_label
78
85
  bottom_img = Tempfile.new(['meme', '.png'])
79
- Cli.run(
80
- convert,
86
+ convert.call(
81
87
  '-background', 'none',
82
88
  '-fill', fill_color,
83
89
  '-stroke', stroke_color,
@@ -94,7 +100,7 @@ module Asciidoctor
94
100
 
95
101
  final_img = Tempfile.new(['meme', ".#{format.to_s}"])
96
102
 
97
- args = [convert, bg_img]
103
+ args = [bg_img]
98
104
  if top_img
99
105
  args << top_img.path << '-geometry' << '+0+0' << '-composite'
100
106
  end
@@ -105,7 +111,7 @@ module Asciidoctor
105
111
 
106
112
  args << final_img.path
107
113
 
108
- Cli.run(*args)
114
+ convert.call(*args)
109
115
 
110
116
  File.binread(final_img)
111
117
  end
@@ -64,9 +64,15 @@ module Asciidoctor
64
64
 
65
65
  opts[:width] = options[:width]
66
66
 
67
- mmdc = source.find_command('mmdc', :raise_on_error => false)
68
- node = source.find_command('node', :raise_on_error => false)
69
- if mmdc && node
67
+ mmdc = nil
68
+ mmdc_exception = nil
69
+ begin
70
+ mmdc = source.find_command('mmdc')
71
+ rescue => e
72
+ mmdc_exception = e
73
+ end
74
+
75
+ if mmdc
70
76
  opts[:height] = options[:height]
71
77
  opts[:scale] = options[:scale]
72
78
  opts[:theme] = options[:theme]
@@ -75,17 +81,25 @@ module Asciidoctor
75
81
  if config
76
82
  opts[:config] = source.resolve_path(config)
77
83
  end
78
- run_mmdc(node, mmdc, source, format, opts)
84
+ run_mmdc(mmdc, source, format, opts)
79
85
  else
80
- mermaid = source.find_command('mermaid')
81
- run_mermaid(mermaid, source, format, opts)
86
+ begin
87
+ mermaid = source.find_command('mermaid')
88
+ run_mermaid(mermaid, source, format, opts)
89
+ rescue
90
+ if mmdc_exception
91
+ raise mmdc_exception
92
+ else
93
+ raise
94
+ end
95
+ end
82
96
  end
83
97
  end
84
98
 
85
99
  private
86
- def run_mmdc(node, mmdc, source, format, options = {})
87
- generate_file(node, 'mmd', format.to_s, source.to_s) do |tool_path, input_path, output_path|
88
- args = [tool_path, '--unhandled-rejections=strict', mmdc, '-i', Platform.native_path(input_path), '-o', Platform.native_path(output_path)]
100
+ def run_mmdc(mmdc, source, format, options = {})
101
+ generate_file(mmdc, 'mmd', format.to_s, source.to_s) do |tool_path, input_path, output_path|
102
+ args = [tool_path, '-i', Platform.native_path(input_path), '-o', Platform.native_path(output_path)]
89
103
 
90
104
  if options[:css]
91
105
  args << '--cssFile' << Platform.native_path(options[:css])
@@ -148,7 +162,10 @@ module Asciidoctor
148
162
  args << '--puppeteerConfigFile' << Platform.native_path(options[:puppeteer])
149
163
  end
150
164
 
151
- args
165
+ {
166
+ :args => args,
167
+ :env => {'NODE_OPTIONS' => '--unhandled-rejections=strict'}
168
+ }
152
169
  end
153
170
  end
154
171
 
@@ -17,9 +17,16 @@ module Asciidoctor
17
17
  def convert(source, format, options)
18
18
  pikchr_path = source.find_command('pikchr')
19
19
 
20
- generate_file_stdout(pikchr_path, format.to_s, source.to_s) do |tool_path, input_path|
20
+ output = generate_file_stdout(pikchr_path, format.to_s, source.to_s) do |tool_path, input_path|
21
21
  [tool_path, "--svg-only", input_path]
22
22
  end
23
+
24
+ if output.start_with? '<svg'
25
+ output
26
+ else
27
+ error = output.gsub(/<\/?[a-z]+>\n?/i, '')
28
+ raise error
29
+ end
23
30
  end
24
31
  end
25
32
  end
@@ -7,15 +7,21 @@ module Asciidoctor
7
7
  class PlantUmlConverter
8
8
  include DiagramConverter
9
9
 
10
- JARS = [
11
- 'plantuml-1.3.15.jar',
12
- 'plantuml.jar',
13
- 'jlatexmath-minimal-1.0.5.jar',
14
- 'batik-all-1.10.jar'
15
- ].map do |jar|
16
- File.expand_path File.join('../..', jar), File.dirname(__FILE__)
17
- end
18
- Java.classpath.concat JARS
10
+ CLASSPATH_ENV = 'DIAGRAM_PLANTUML_CLASSPATH'
11
+ LIB_DIR = File.expand_path('../..', File.dirname(__FILE__))
12
+ PLANTUML_JARS = if ENV.has_key?(CLASSPATH_ENV)
13
+ ENV[CLASSPATH_ENV].split(File::PATH_SEPARATOR)
14
+ else
15
+ begin
16
+ require 'asciidoctor-diagram/plantuml/classpath'
17
+ ::Asciidoctor::Diagram::PlantUmlClasspath::JAR_FILES
18
+ rescue LoadError
19
+ raise "Could not load PlantUML. Eiter require 'asciidoctor-diagram-plantuml' or specify the location of the PlantUML JAR(s) using the 'DIAGRAM_PLANTUML_CLASSPATH' environment variable."
20
+ end
21
+ end
22
+
23
+ Java.classpath.concat Dir[File.join(File.dirname(__FILE__), '*.jar')].freeze
24
+ Java.classpath.concat PLANTUML_JARS
19
25
 
20
26
  def supported_formats
21
27
  [:png, :svg, :txt, :atxt, :utxt]
@@ -14,6 +14,10 @@ module Asciidoctor
14
14
  [:svg]
15
15
  end
16
16
 
17
+ def native_scaling?
18
+ true
19
+ end
20
+
17
21
  OPTIONS = {
18
22
  :font_family => lambda { |o, v| o << '--font-family' << v if v },
19
23
  :font_size => lambda { |o, v| o << '--font-size' << v if v },
@@ -12,7 +12,16 @@ module Asciidoctor
12
12
  opts = args.pop.dup if args.last.is_a? Hash
13
13
  in_data = opts && opts[:stdin_data]
14
14
 
15
+ if Hash === args.first
16
+ env = args.shift.dup
17
+ else
18
+ env = {}
19
+ end
20
+
15
21
  pb = java.lang.ProcessBuilder.new(*args)
22
+ env.each_pair do |key, value|
23
+ pb.environment.put(key, value)
24
+ end
16
25
  p = pb.start
17
26
 
18
27
  stdout = ""
@@ -67,12 +76,18 @@ module Asciidoctor
67
76
  opts = {}
68
77
  end
69
78
 
79
+ if Hash === args.first
80
+ env = args.shift.dup
81
+ else
82
+ env = {}
83
+ end
84
+
70
85
  # When the first argument is an array, we force capture3 (or better the underlying Kernel#spawn)
71
86
  # to use a non-shell execution variant.
72
87
  cmd = File.basename(args[0])
73
88
  args[0] = [args[0], cmd]
74
89
 
75
- stdout, stderr, status = Open3.capture3(*args, opts)
90
+ stdout, stderr, status = Open3.capture3(env, *args, opts)
76
91
 
77
92
  exit = status.exitstatus
78
93
 
@@ -74,15 +74,17 @@ module Asciidoctor
74
74
  when Array
75
75
  args = opts
76
76
  out_file = nil
77
+ env = {}
77
78
  when Hash
78
79
  args = opts[:args]
79
80
  out_file = opts[:out_file]
81
+ env = opts[:env] || {}
80
82
  else
81
83
  raise "Block passed to generate_file should return an Array or a Hash"
82
84
  end
83
85
 
84
- logger.debug "Executing #{args} with options #{open3_opts}"
85
- result = ::Asciidoctor::Diagram::Cli.run(*args, open3_opts)
86
+ logger.debug "Executing #{args} with options #{open3_opts} and environment #{env}"
87
+ result = ::Asciidoctor::Diagram::Cli.run(env, *args, open3_opts)
86
88
 
87
89
  data = target_file == :stdout ? result[:out] : read_result(target_file, out_file)
88
90
 
@@ -7,7 +7,7 @@ module Asciidoctor
7
7
  GIF87A_SIGNATURE = 'GIF87a'.force_encoding(Encoding::ASCII_8BIT)
8
8
  GIF89A_SIGNATURE = 'GIF89a'.force_encoding(Encoding::ASCII_8BIT)
9
9
 
10
- def self.post_process_image(data)
10
+ def self.post_process_image(data, optimise)
11
11
  bio = BinaryIO.new(data)
12
12
  gif_signature = bio.read_string(6)
13
13
  raise "Invalid GIF signature" unless gif_signature == GIF87A_SIGNATURE || gif_signature == GIF89A_SIGNATURE
@@ -5,9 +5,7 @@ module Asciidoctor
5
5
  # @private
6
6
  module Java
7
7
  def self.classpath
8
- @classpath ||= [
9
- File.expand_path(File.join('../..', 'server-1.3.15.jar'), File.dirname(__FILE__))
10
- ]
8
+ @classpath ||= Dir[File.join(File.dirname(__FILE__), '*.jar')]
11
9
  end
12
10
 
13
11
  CRLF = "\r\n".encode(Encoding::US_ASCII)
@@ -53,6 +51,10 @@ module Asciidoctor
53
51
  io.set_encoding Encoding::US_ASCII
54
52
  status_line = io.readline(CRLF)
55
53
  status_line_parts = STATUS_LINE.match status_line
54
+ unless status_line_parts
55
+ raise "Unexpected HTTP status line: #{status_line}"
56
+ end
57
+
56
58
  resp[:code] = status_line_parts[1].to_i
57
59
  resp[:reason] = status_line_parts[2]
58
60