vectory 0.3.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 865823bf5ac58c0780cdffc76abf7d396c2b481bcf292c807e419c0983f44646
4
- data.tar.gz: cd29b9a6f1c3a851e37fa207427474a60656ad8a1ba6f27d954d08d2ded47f5d
3
+ metadata.gz: 2f51d610adc333c06f92e8e28ca9722a890f12b03668bf12e96ce057d2574dea
4
+ data.tar.gz: 792bc815a0b86a6211b83268f16b9abe7a138aba0081a2d7a95242c5e9a7af82
5
5
  SHA512:
6
- metadata.gz: 01ee6626bca7c7a61f14dffa639355171e052637f9b1c58d4dfb39721a7b7a815e6b11cd5c1deb76b4faecba37abf873e45661c16ebd2eaf7434cb9031a6deff
7
- data.tar.gz: 6706861380815c36d273445cc970db3b01693024208596c8072e9661ab301908db5c6c81e7d707826b501263aac8dbcc4b65f553fc62857a773cb45404d53de4
6
+ metadata.gz: 249d3f2fa7df2d216cdf5d046647507b81a55bd5db56a603a90a3890501adb10e8a03f41b272385c65a8de48c50b8b52db743ec5ddc20be88e4e5aab6ed21ca6
7
+ data.tar.gz: 5ed331050b3c4a3231cabc7ba061695f017de5ea44a3056bf01537144b12c96cf5587c0a52793d3d435d961052210aefed73a52c4afc9c3563695fca8e23c91d
data/README.adoc CHANGED
@@ -329,6 +329,23 @@ purposes.
329
329
  vector.initial_path # => "storage/images/img.eps"
330
330
  ----
331
331
 
332
+ ==== Additional properties
333
+
334
+ The following additional properties are supported:
335
+
336
+ [source,ruby]
337
+ ----
338
+ Datauri#mime
339
+ Datauri#height
340
+ Datauri#width
341
+ Vector (Eps, Ps, Svg, Emf)
342
+ Vector#mime
343
+ Vector#size
344
+ Vector#file_size
345
+ Vector#height
346
+ Vector#width
347
+ ----
348
+
332
349
 
333
350
  == Development
334
351
 
@@ -18,6 +18,19 @@ module Vectory
18
18
  new("data:#{mimetype};base64,#{data}")
19
19
  end
20
20
 
21
+ def mime
22
+ match = parse_datauri(@content)
23
+ match[:mimetype]
24
+ end
25
+
26
+ def height
27
+ to_vector.height
28
+ end
29
+
30
+ def width
31
+ to_vector.width
32
+ end
33
+
21
34
  def to_vector
22
35
  match = parse_datauri(@content)
23
36
  content = Base64.strict_decode64(match[:data])
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "singleton"
4
+ require "tmpdir"
4
5
  require_relative "system_call"
5
6
 
6
7
  module Vectory
@@ -12,7 +13,7 @@ module Vectory
12
13
  end
13
14
 
14
15
  def convert(uri, output_extension, option)
15
- exe = inkscape_path_or_raise_error(uri)
16
+ exe = inkscape_path_or_raise_error
16
17
  uri = external_path uri
17
18
  exe = external_path exe
18
19
  cmd = %(#{exe} #{option} #{uri})
@@ -27,12 +28,20 @@ module Vectory
27
28
  output_path
28
29
  end
29
30
 
31
+ def height(content, format)
32
+ query_integer(content, format, "--query-height")
33
+ end
34
+
35
+ def width(content, format)
36
+ query_integer(content, format, "--query-width")
37
+ end
38
+
30
39
  private
31
40
 
32
- def inkscape_path_or_raise_error(path)
41
+ def inkscape_path_or_raise_error
33
42
  inkscape_path or raise(InkscapeNotFoundError,
34
43
  "Inkscape missing in PATH, unable to " \
35
- "convert image #{path}. Aborting.")
44
+ "convert image. Aborting.")
36
45
  end
37
46
 
38
47
  def inkscape_path
@@ -95,5 +104,40 @@ module Vectory
95
104
  path
96
105
  end
97
106
  end
107
+
108
+ def query_integer(content, format, options)
109
+ query(content, format, options).to_f.round
110
+ end
111
+
112
+ def query(content, format, options)
113
+ exe = inkscape_path_or_raise_error
114
+
115
+ with_file(content, format) do |path|
116
+ cmd = "#{external_path(exe)} #{options} #{external_path(path)}"
117
+
118
+ call = SystemCall.new(cmd).call
119
+ raise_query_error(call) if call.stdout.empty?
120
+
121
+ call.stdout
122
+ end
123
+ end
124
+
125
+ def with_file(content, extension)
126
+ Dir.mktmpdir do |dir|
127
+ path = File.join(dir, "image.#{extension}")
128
+ File.binwrite(path, content)
129
+
130
+ yield path
131
+ end
132
+ end
133
+
134
+ def raise_query_error(call)
135
+ raise Vectory::InkscapeQueryError,
136
+ "Could not query with Inkscape. " \
137
+ "Inkscape cmd: '#{call.cmd}',\n" \
138
+ "status: '#{call.status}',\n" \
139
+ "stdout: '#{call.stdout.strip}',\n" \
140
+ "stderr: '#{call.stderr.strip}'."
141
+ end
98
142
  end
99
143
  end
@@ -33,7 +33,6 @@ module Vectory
33
33
  result = Utils.capture3_with_timeout(cmd,
34
34
  timeout: @timeout,
35
35
  kill_after: @timeout)
36
- Vectory.ui.error(result.inspect)
37
36
  @stdout = result[:stdout]
38
37
  @stderr = result[:stderr]
39
38
  @status = result[:status]
@@ -28,6 +28,28 @@ module Vectory
28
28
  @initial_path = initial_path
29
29
  end
30
30
 
31
+ def mime
32
+ self.class.mimetype
33
+ end
34
+
35
+ def size
36
+ content.bytesize
37
+ end
38
+
39
+ def file_size
40
+ raise(NotWrittenToDiskError) unless @path
41
+
42
+ File.size(@path)
43
+ end
44
+
45
+ def height
46
+ InkscapeConverter.instance.height(content, self.class.default_extension)
47
+ end
48
+
49
+ def width
50
+ InkscapeConverter.instance.width(content, self.class.default_extension)
51
+ end
52
+
31
53
  def to_uri
32
54
  Datauri.from_vector(self)
33
55
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Vectory
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
data/lib/vectory.rb CHANGED
@@ -21,6 +21,8 @@ module Vectory
21
21
 
22
22
  class InkscapeNotFoundError < Error; end
23
23
 
24
+ class InkscapeQueryError < Error; end
25
+
24
26
  class NotImplementedError < Error; end
25
27
 
26
28
  class NotWrittenToDiskError < Error; end
@@ -1,3 +1,15 @@
1
+ RSpec::Matchers.define :be_eps do
2
+ match do |actual|
3
+ actual.start_with?("%!PS-Adobe-3.0")
4
+ end
5
+ end
6
+
7
+ RSpec::Matchers.define :be_svg do
8
+ match do |actual|
9
+ actual.include?("<svg")
10
+ end
11
+ end
12
+
1
13
  RSpec::Matchers.define :be_equivalent_eps_to do |expected|
2
14
  match do |actual|
3
15
  e = sub_time_and_version(expected)
@@ -11,10 +11,11 @@ RSpec.describe Vectory::CLI do
11
11
  shared_examples "converter" do |format|
12
12
  it "creates file of a chosen format" do
13
13
  matcher = case format
14
- when "eps", "ps" then "be_equivalent_eps_to"
15
- when "svg" then "be_equivalent_svg_to"
14
+ when "eps", "ps" then "be_eps"
15
+ when "svg" then "be_svg"
16
16
  else "be_equivalent_to"
17
17
  end
18
+
18
19
  with_tmp_dir do |dir|
19
20
  output = File.join(dir, "output.#{format}")
20
21
  status = described_class.start(["-f", format, "-o", output, input])
@@ -98,4 +98,84 @@ RSpec.describe Vectory::Datauri do
98
98
  end
99
99
  end
100
100
  end
101
+
102
+ describe "#mime" do
103
+ context "incorrect data" do
104
+ let(:not_a_datauri) { "123abc" }
105
+
106
+ it "raises conversion error" do
107
+ expect { described_class.new(not_a_datauri).mime }
108
+ .to raise_error(Vectory::ConversionError)
109
+ end
110
+ end
111
+
112
+ context "eps" do
113
+ let(:input) { "spec/examples/eps2emf/img.eps.datauri" }
114
+
115
+ it "returns eps" do
116
+ expect(described_class.from_path(input).mime)
117
+ .to eq "application/postscript"
118
+ end
119
+ end
120
+
121
+ context "emf" do
122
+ let(:input) { "spec/examples/emf2eps/img.emf.datauri" }
123
+
124
+ it "returns emf" do
125
+ expect(described_class.from_path(input).mime).to eq "image/emf"
126
+ end
127
+ end
128
+
129
+ context "svg" do
130
+ let(:input) { "spec/examples/svg2emf/img.svg.datauri" }
131
+
132
+ it "returns svg" do
133
+ expect(described_class.from_path(input).mime).to eq "image/svg+xml"
134
+ end
135
+ end
136
+ end
137
+
138
+ describe "dimensions (#height / #width)" do
139
+ context "incorrect data" do
140
+ let(:not_a_datauri) { "123abc" }
141
+
142
+ it "raises conversion error" do
143
+ expect { described_class.new(not_a_datauri).height }
144
+ .to raise_error(Vectory::ConversionError)
145
+
146
+ expect { described_class.new(not_a_datauri).width }
147
+ .to raise_error(Vectory::ConversionError)
148
+ end
149
+ end
150
+
151
+ context "eps" do
152
+ let(:input) { "spec/examples/eps2emf/img.eps.datauri" }
153
+
154
+ it "returns height and width" do
155
+ expect(described_class.from_path(input).height)
156
+ .to eq 707
157
+
158
+ expect(described_class.from_path(input).width)
159
+ .to eq 649
160
+ end
161
+ end
162
+
163
+ context "emf" do
164
+ let(:input) { "spec/examples/emf2eps/img.emf.datauri" }
165
+
166
+ it "returns height and width" do
167
+ expect(described_class.from_path(input).height).to eq 90
168
+ expect(described_class.from_path(input).width).to eq 90
169
+ end
170
+ end
171
+
172
+ context "svg" do
173
+ let(:input) { "spec/examples/svg2emf/img.svg.datauri" }
174
+
175
+ it "returns height and width" do
176
+ expect(described_class.from_path(input).height).to eq 90
177
+ expect(described_class.from_path(input).width).to eq 90
178
+ end
179
+ end
180
+ end
101
181
  end
@@ -35,4 +35,28 @@ RSpec.describe Vectory::Emf do
35
35
  .to be_equivalent_eps_to File.read(reference)
36
36
  end
37
37
  end
38
+
39
+ describe "#mime" do
40
+ let(:input) { "spec/examples/emf2eps/img.emf" }
41
+
42
+ it "returns emf" do
43
+ expect(described_class.from_path(input).mime).to eq "image/emf"
44
+ end
45
+ end
46
+
47
+ describe "#height" do
48
+ let(:input) { "spec/examples/emf2eps/img.emf" }
49
+
50
+ it "returns height" do
51
+ expect(described_class.from_path(input).height).to eq 90
52
+ end
53
+ end
54
+
55
+ describe "#width" do
56
+ let(:input) { "spec/examples/emf2eps/img.emf" }
57
+
58
+ it "returns width" do
59
+ expect(described_class.from_path(input).width).to eq 90
60
+ end
61
+ end
38
62
  end
@@ -3,16 +3,18 @@ require "spec_helper"
3
3
  RSpec.describe Vectory::Eps do
4
4
  shared_examples "converter" do |format|
5
5
  it "returns content of a chosen format" do
6
+ to_format_method = "to_#{format}"
7
+ content = described_class.from_path(input)
8
+ .public_send(to_format_method)
9
+ .content
10
+
6
11
  matcher = case format
7
- when "eps", "ps" then "be_equivalent_eps_to"
8
- when "svg" then "be_equivalent_svg_to"
12
+ when "eps", "ps" then "be_eps"
13
+ when "svg" then "be_svg"
9
14
  else "be_equivalent_to"
10
15
  end
11
16
 
12
- to_format_method = "to_#{format}"
13
- expect(described_class.from_path(input)
14
- .public_send(to_format_method)
15
- .content)
17
+ expect(content)
16
18
  .to public_send(matcher, File.read(reference))
17
19
  end
18
20
  end
@@ -37,4 +39,29 @@ RSpec.describe Vectory::Eps do
37
39
 
38
40
  it_behaves_like "converter", "emf"
39
41
  end
42
+
43
+ describe "#mime" do
44
+ let(:input) { "spec/examples/eps2emf/img.eps" }
45
+
46
+ it "returns postscript" do
47
+ expect(described_class.from_path(input).mime)
48
+ .to eq "application/postscript"
49
+ end
50
+ end
51
+
52
+ describe "#height" do
53
+ let(:input) { "spec/examples/eps2emf/img.eps" }
54
+
55
+ it "returns height" do
56
+ expect(described_class.from_path(input).height).to eq 707
57
+ end
58
+ end
59
+
60
+ describe "#width" do
61
+ let(:input) { "spec/examples/eps2emf/img.eps" }
62
+
63
+ it "returns width" do
64
+ expect(described_class.from_path(input).width).to eq 649
65
+ end
66
+ end
40
67
  end
@@ -30,4 +30,29 @@ RSpec.describe Vectory::Ps do
30
30
  .to be_equivalent_svg_to File.read(reference)
31
31
  end
32
32
  end
33
+
34
+ describe "#mime" do
35
+ let(:input) { "spec/examples/ps2emf/img.ps" }
36
+
37
+ it "returns postscript" do
38
+ expect(described_class.from_path(input).mime)
39
+ .to eq "application/postscript"
40
+ end
41
+ end
42
+
43
+ describe "#height" do
44
+ let(:input) { "spec/examples/ps2emf/img.ps" }
45
+
46
+ it "returns height" do
47
+ expect(described_class.from_path(input).height).to eq 707
48
+ end
49
+ end
50
+
51
+ describe "#width" do
52
+ let(:input) { "spec/examples/ps2emf/img.ps" }
53
+
54
+ it "returns width" do
55
+ expect(described_class.from_path(input).width).to eq 649
56
+ end
57
+ end
33
58
  end
@@ -38,4 +38,36 @@ RSpec.describe Vectory::Svg do
38
38
  .to be_equivalent_eps_to File.read(reference)
39
39
  end
40
40
  end
41
+
42
+ describe "#mime" do
43
+ let(:input) { "spec/examples/svg2emf/img.svg" }
44
+
45
+ it "returns svg" do
46
+ expect(described_class.from_path(input).mime).to eq "image/svg+xml"
47
+ end
48
+ end
49
+
50
+ describe "#height" do
51
+ let(:input) { "spec/examples/svg2emf/img.svg" }
52
+
53
+ it "returns height" do
54
+ expect(described_class.from_path(input).height).to eq 90
55
+ end
56
+
57
+ context "incorrect data" do
58
+ let(:command) { described_class.from_content("incorrect123svg") }
59
+
60
+ it "raises query error" do
61
+ expect { command.height }.to raise_error(Vectory::InkscapeQueryError)
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "#width" do
67
+ let(:input) { "spec/examples/svg2emf/img.svg" }
68
+
69
+ it "returns width" do
70
+ expect(described_class.from_path(input).width).to eq 90
71
+ end
72
+ end
41
73
  end
@@ -56,5 +56,42 @@ RSpec.describe Vectory::Vector do
56
56
  expect { image.path }.to raise_error(Vectory::NotWrittenToDiskError)
57
57
  end
58
58
  end
59
+
60
+ context "written to disk" do
61
+ before { image.write }
62
+
63
+ it "returns path on a disk" do
64
+ expect(image.path).to include(Dir.tmpdir)
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "#size" do
70
+ let(:image) { Vectory::Emf.from_path("spec/examples/emf2svg/img.emf") }
71
+
72
+ it "returns content size" do
73
+ expect(image.size).to eq 1060
74
+ end
75
+ end
76
+
77
+ describe "#file_size" do
78
+ let(:image) { Vectory::Eps.from_path("spec/examples/eps2emf/img.eps") }
79
+
80
+ context "not written to disk" do
81
+ it "raises not-written error" do
82
+ expect { image.file_size }
83
+ .to raise_error(Vectory::NotWrittenToDiskError)
84
+ end
85
+ end
86
+
87
+ context "written to disk" do
88
+ before { image.write }
89
+
90
+ it "returns file size" do
91
+ expect(image.file_size).to satisfy("be either 2926 or 3125") do |v|
92
+ [2926, 3125].include?(v) # depends on file system
93
+ end
94
+ end
95
+ end
59
96
  end
60
97
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vectory
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-30 00:00:00.000000000 Z
11
+ date: 2023-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: emf2svg