vectory 0.10.1 → 0.12.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: fbf800fda7352c671459d15edf027eebb640c22e15d442ea56c4d53a8776fd2b
4
- data.tar.gz: ee2f5cc26a74337d76323da92f1a6abde859436022a976eac8966421aa86c86a
3
+ metadata.gz: 3a9abbde7cd6a7876ad8a2f8077786e870dcf860b3206bef30f061f997145d31
4
+ data.tar.gz: 05c8f3c7a6ab01aa09e3facc83d145ba17a6a8ea7dde5e2bba02ab1405d49999
5
5
  SHA512:
6
- metadata.gz: c080dbacd92170ef37bc37664caba98f95378ef90730985734dd5568a4db4a43416c09a90cacc1fb2392b121ceb117ce3474ad9c8ae301652d8c6ca030cc1d98
7
- data.tar.gz: 617496862f207a82ce61695638cbb5b5061d230e18c1f8835bdb3183e763075460539fc9398ed1c1a28352e0615b1a7bad6c62165b525a6ec3ce912d95cead7b
6
+ metadata.gz: a9651cbe852b2ba5dbdbdb07db31105aa33bf9a41bcc7bd0cb4f621c679ba41f4343f85ae0d4f3722a34cfaab2cb4cb80210e2aa383b71d7df34256b36a781ac
7
+ data.tar.gz: c03d30678dfa73b41dac5b987cd70905fc0edc2dcd5621a7bdfb2d61bf8be11769f1d4135602c93aa7b51b243e05b915d0c7b0e55f5002badc50d45365863e3a
data/README.adoc CHANGED
@@ -21,14 +21,12 @@ ____
21
21
 
22
22
  === Prerequisites
23
23
 
24
- Vectory relies on the following software to be installed:
24
+ Vectory ships as a pure-Ruby gem. Format support is provided by these Ruby gems (installed automatically):
25
25
 
26
- * https://github.com/claricle/emfsvg[emfsvg]
27
- * https://inkscape.org[Inkscape]
28
- * https://www.ghostscript.com/[Ghostscript]
26
+ * https://github.com/claricle/emfsvg[emfsvg] (EMF <-> SVG)
27
+ * https://github.com/claricle/postsvg[postsvg] (PS/EPS <-> SVG)
29
28
 
30
- NOTE: Inkscape 1.3.1+ does not work properly with EPS/PS on Windows. To avoid
31
- this issue, the 1.3.0 version of Inkscape can be used.
29
+ No external binaries are required.
32
30
 
33
31
 
34
32
  === Gem install
@@ -32,21 +32,22 @@ svg_to_eps = Vectory::Svg.from_path("diagram.svg").to_eps
32
32
  eps_to_svg = Vectory::Eps.from_path("diagram.eps").to_svg
33
33
  ----
34
34
 
35
- === Two-Step Conversions (EPS/PS → SVG)
35
+ === Direct Conversions (via postsvg)
36
36
 
37
- EPS and PS files are converted to SVG through a PDF intermediate:
38
-
39
- 1. **EPS/PS → PDF** (via Ghostscript): Preserves BoundingBox information
40
- 2. **PDF → SVG** (via Inkscape): Converts PDF to SVG
37
+ EPS and PS files are converted to SVG directly by the postsvg gem (pure Ruby, no Ghostscript or Inkscape):
41
38
 
42
39
  [source,ruby]
43
40
  ----
44
- # Two-step conversion (automatic)
45
41
  eps = Vectory::Eps.from_path("diagram.eps")
46
- svg = eps.to_svg # Internally: EPS → PDF → SVG
42
+ svg = eps.to_svg # Uses postsvg directly
43
+
44
+ ps = Vectory::Ps.from_path("diagram.ps")
45
+ svg = ps.to_svg # Also postsvg
47
46
  ----
48
47
 
49
- This two-step process ensures accurate dimension preservation from EPS/PS files.
48
+ postsvg reads the `%%BoundingBox` DSC comment to size the viewBox. Limitations: text/font rendering, image embedding, gradients/patterns, CMYK, and PS Level 2/3 advanced operators are not yet supported by postsvg upstream — EPS/PS files using those features will silently degrade.
49
+
50
+ === Two-Step Conversions (EPS/PS → PDF/PS/EMF)
50
51
 
51
52
  === EMF Conversions (via emfsvg)
52
53
 
@@ -73,11 +74,11 @@ emf = Vectory::Svg.from_path("chart.svg").to_emf
73
74
  |SVG|EMF|emfsvg gem
74
75
  |SVG|PDF|Inkscape
75
76
 
76
- |EPS|SVG|Ghostscript + Inkscape (two-step)
77
+ |EPS|SVG|postsvg gem
77
78
  |EPS|PDF|Ghostscript
78
79
  |EPS|PS|Via PDF intermediate
79
80
 
80
- |PS|SVG|Ghostscript + Inkscape (two-step)
81
+ |PS|SVG|postsvg gem
81
82
  |PS|PDF|Ghostscript
82
83
  |PS|EPS|Via PDF intermediate
83
84
 
@@ -68,23 +68,30 @@ Vectory uses different external tools depending on the source and target formats
68
68
 
69
69
  === Direct Conversions (via Inkscape)
70
70
 
71
- * **SVG → EPS/PS/EMF/PDF** (via Inkscape export)
72
- * **EPS/PS/EMF/PDF → SVG** (via Inkscape import)
71
+ * **SVG → EPS/PS/PDF** (via Inkscape export)
72
+ * **PDF → SVG** (via Inkscape import)
73
73
 
74
74
  Inkscape handles direct conversions to and from SVG format.
75
75
 
76
76
  === Direct Conversions (via emfsvg)
77
77
 
78
- * **EMF SVG** (via emfsvg gem)
78
+ * **SVG EMF** (via emfsvg gem, both directions)
79
79
 
80
- The emfsvg gem provides native EMF to SVG conversion in pure Ruby, with no external tool dependency.
80
+ The emfsvg gem provides bidirectional EMF SVG conversion in pure Ruby, with no external tool dependency.
81
+
82
+ === Direct Conversions (via postsvg)
83
+
84
+ * **EPS → SVG** (via postsvg gem)
85
+ * **PS → SVG** (via postsvg gem)
86
+
87
+ The postsvg gem converts PS/EPS to SVG in pure Ruby, with no external tool dependency.
81
88
 
82
89
  === Two-Step Conversions (via Ghostscript + Inkscape)
83
90
 
84
- * **EPS → PDF → SVG** (Ghostscript for EPS→PDF, Inkscape for PDF→SVG)
85
- * **PS → PDF → SVG** (Ghostscript for PS→PDF, Inkscape for PDF→SVG)
91
+ * **EPS → PDF → SVG** (legacy path; replaced by postsvg for `Eps#to_svg`)
92
+ * **PS → PDF → SVG** (legacy path; replaced by postsvg for `Ps#to_svg`)
86
93
 
87
- This two-step process preserves BoundingBox information from EPS/PS files.
94
+ EPS/PS PDF and EPS/PS → PS/EMF (via PDF intermediate) still go through Ghostscript.
88
95
 
89
96
  === Conversion Tool Matrix
90
97
 
@@ -95,11 +95,12 @@ Vectory uses a flexible conversion pipeline:
95
95
  Some conversions are direct:
96
96
  * **SVG → EPS/PS/PDF**: Via Inkscape
97
97
  * **SVG ↔ EMF**: Via emfsvg (both directions, pure Ruby)
98
+ * **EPS → SVG** and **PS → SVG**: Via postsvg (pure Ruby)
98
99
 
99
100
  === Two-Step Conversions
100
101
 
101
102
  Other conversions use an intermediate PDF format:
102
- * **EPS/PS → PDF → SVG**: Via Ghostscript + Inkscape
103
+ * **EPS/PS → PDF → {PS,EMF}**: Via Ghostscript + Inkscape
103
104
 
104
105
  This two-step conversion ensures:
105
106
  * BoundingBox preservation from EPS/PS
data/lib/vectory/cli.rb CHANGED
@@ -9,14 +9,10 @@ module Vectory
9
9
  STATUS_UNSUPPORTED_OUTPUT_FORMAT_ERROR = 3
10
10
  STATUS_CONVERSION_ERROR = 4
11
11
  STATUS_SYSTEM_CALL_ERROR = 5
12
- STATUS_INKSCAPE_NOT_FOUND_ERROR = 6
13
12
  STATUS_SAME_FORMAT_ERROR = 7
14
- STATUS_GHOSTSCRIPT_NOT_FOUND_ERROR = 8
15
13
 
16
14
  MAP_ERROR_TO_STATUS = {
17
15
  Vectory::ConversionError => STATUS_CONVERSION_ERROR,
18
- Vectory::InkscapeNotFoundError => STATUS_INKSCAPE_NOT_FOUND_ERROR,
19
- Vectory::GhostscriptNotFoundError => STATUS_GHOSTSCRIPT_NOT_FOUND_ERROR,
20
16
  Vectory::SystemCallError => STATUS_SYSTEM_CALL_ERROR,
21
17
  }.freeze
22
18
 
@@ -3,14 +3,10 @@
3
3
  module Vectory
4
4
  # Configuration for Vectory
5
5
  #
6
- # Provides centralized configuration for tool paths, timeouts, caching, etc.
6
+ # Provides centralized configuration for timeouts, caching, etc.
7
7
  # Can be loaded from environment variables or a configuration file.
8
8
  #
9
- # @example Set custom Inkscape path
10
- # Vectory::Configuration.instance.inkscape_path = "/path/to/inkscape"
11
- #
12
9
  # @example Load from environment variables
13
- # # Set VECTORY_INKSCAPE_PATH environment variable
14
10
  # Vectory::Configuration.load_from_environment
15
11
  class Configuration
16
12
  # Default timeout for external tool execution (seconds)
@@ -22,8 +18,8 @@ module Vectory
22
18
  # Default temporary directory
23
19
  DEFAULT_TEMP_DIR = nil # Use system default
24
20
 
25
- attr_accessor :inkscape_path, :ghostscript_path, :timeout, :cache_ttl,
26
- :cache_enabled, :temp_dir, :verbose_logging
21
+ attr_accessor :timeout, :cache_ttl, :cache_enabled, :temp_dir,
22
+ :verbose_logging
27
23
 
28
24
  # Get the singleton instance
29
25
  #
@@ -46,15 +42,11 @@ module Vectory
46
42
  @cache_enabled = true
47
43
  @temp_dir = DEFAULT_TEMP_DIR
48
44
  @verbose_logging = false
49
- @inkscape_path = nil
50
- @ghostscript_path = nil
51
45
  end
52
46
 
53
47
  # Load configuration from environment variables
54
48
  #
55
49
  # Supported environment variables:
56
- # - VECTORY_INKSCAPE_PATH: Path to Inkscape executable
57
- # - VECTORY_GHOSTSCRIPT_PATH: Path to Ghostscript executable
58
50
  # - VECTORY_TIMEOUT: Timeout for external tools (default: 120)
59
51
  # - VECTORY_CACHE_TTL: Cache TTL in seconds (default: 300)
60
52
  # - VECTORY_CACHE_ENABLED: Enable/disable caching (default: true)
@@ -65,8 +57,6 @@ module Vectory
65
57
  def self.load_from_environment
66
58
  config = instance
67
59
 
68
- config.inkscape_path = ENV["VECTORY_INKSCAPE_PATH"] if ENV["VECTORY_INKSCAPE_PATH"]
69
- config.ghostscript_path = ENV["VECTORY_GHOSTSCRIPT_PATH"] if ENV["VECTORY_GHOSTSCRIPT_PATH"]
70
60
  config.timeout = ENV["VECTORY_TIMEOUT"]&.to_i || config.timeout
71
61
  config.cache_ttl = ENV["VECTORY_CACHE_TTL"]&.to_i || config.cache_ttl
72
62
  config.cache_enabled = ENV["VECTORY_CACHE_ENABLED"] != "false"
@@ -86,8 +76,6 @@ module Vectory
86
76
  config_data = YAML.load_file(path)
87
77
 
88
78
  config = instance
89
- config.inkscape_path = config_data["inkscape_path"] if config_data["inkscape_path"]
90
- config.ghostscript_path = config_data["ghostscript_path"] if config_data["ghostscript_path"]
91
79
  config.timeout = config_data["timeout"] || config.timeout
92
80
  config.cache_ttl = config_data["cache_ttl"] || config.cache_ttl
93
81
  config.cache_enabled = config_data.fetch("cache_enabled",
@@ -104,8 +92,6 @@ module Vectory
104
92
  # @return [Hash] the configuration as a hash
105
93
  def to_h
106
94
  {
107
- inkscape_path: @inkscape_path,
108
- ghostscript_path: @ghostscript_path,
109
95
  timeout: @timeout,
110
96
  cache_ttl: @cache_ttl,
111
97
  cache_enabled: @cache_enabled,
@@ -114,20 +100,6 @@ module Vectory
114
100
  }
115
101
  end
116
102
 
117
- # Get the Inkscape path (custom or auto-detected)
118
- #
119
- # @return [String, nil] the configured Inkscape path or nil if not set
120
- def effective_inkscape_path
121
- @inkscape_path
122
- end
123
-
124
- # Get the Ghostscript path (custom or auto-detected)
125
- #
126
- # @return [String, nil] the configured Ghostscript path or nil if not set
127
- def effective_ghostscript_path
128
- @ghostscript_path
129
- end
130
-
131
103
  # Check if caching is enabled
132
104
  #
133
105
  # @return [Boolean] true if caching is enabled
data/lib/vectory/emf.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "emf"
3
4
  require "emfsvg"
4
5
 
5
6
  module Vectory
@@ -32,21 +33,33 @@ module Vectory
32
33
  end
33
34
 
34
35
  def to_eps
35
- InkscapeWrapper.convert(
36
- content: content,
37
- input_format: :emf,
38
- output_format: :eps,
39
- output_class: Eps,
40
- )
36
+ to_svg.to_eps
41
37
  end
42
38
 
43
39
  def to_ps
44
- InkscapeWrapper.convert(
45
- content: content,
46
- input_format: :emf,
47
- output_format: :ps,
48
- output_class: Ps,
49
- )
40
+ to_svg.to_ps
41
+ end
42
+
43
+ def height
44
+ bounds = parse_header_bounds
45
+ return super unless bounds
46
+
47
+ bounds.bottom - bounds.top
48
+ end
49
+
50
+ def width
51
+ bounds = parse_header_bounds
52
+ return super unless bounds
53
+
54
+ bounds.right - bounds.left
55
+ end
56
+
57
+ private
58
+
59
+ def parse_header_bounds
60
+ ::Emf.parse(content).header.bounds
61
+ rescue StandardError
62
+ nil
50
63
  end
51
64
  end
52
65
  end
data/lib/vectory/eps.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "postsvg"
4
+
3
5
  module Vectory
4
6
  class Eps < Vector
5
7
  def self.default_extension
@@ -20,27 +22,15 @@ module Vectory
20
22
  end
21
23
 
22
24
  def to_ps
23
- to_pdf.to_ps
25
+ to_svg.to_ps
24
26
  end
25
27
 
26
28
  def to_svg
27
- to_pdf.to_svg
29
+ Svg.from_content(Postsvg.convert(content))
28
30
  end
29
31
 
30
32
  def to_emf
31
- to_pdf.to_emf
32
- end
33
-
34
- def to_pdf
35
- pdf_content = GhostscriptWrapper.convert(content, eps_crop: true)
36
- pdf = Pdf.new(pdf_content)
37
- # Pass original BoundingBox dimensions to preserve them in conversions
38
- bbox = parse_bounding_box
39
- if bbox
40
- pdf.original_width = bbox[:urx] - bbox[:llx]
41
- pdf.original_height = bbox[:ury] - bbox[:lly]
42
- end
43
- pdf
33
+ to_svg.to_emf
44
34
  end
45
35
 
46
36
  def height
@@ -3,20 +3,6 @@
3
3
  module Vectory
4
4
  class ConversionError < Error; end
5
5
 
6
- class InkscapeNotFoundError < Error
7
- def initialize(msg = nil)
8
- super(msg || "Inkscape not found in PATH. Please install Inkscape.")
9
- end
10
- end
11
-
12
- class GhostscriptNotFoundError < Error
13
- def initialize(msg = nil)
14
- super(msg || "Ghostscript not found in PATH. Please install Ghostscript.")
15
- end
16
- end
17
-
18
- class InkscapeQueryError < Error; end
19
-
20
6
  class InvalidFormatError < Error
21
7
  def initialize(format, supported_formats)
22
8
  super("Invalid format '#{format}'. Supported formats: #{supported_formats.join(', ')}")
data/lib/vectory/ps.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "postsvg"
4
+
3
5
  module Vectory
4
6
  class Ps < Vector
5
7
  def self.default_extension
@@ -20,27 +22,15 @@ module Vectory
20
22
  end
21
23
 
22
24
  def to_eps
23
- to_pdf.to_eps
25
+ to_svg.to_eps
24
26
  end
25
27
 
26
28
  def to_emf
27
- to_pdf.to_emf
29
+ to_svg.to_emf
28
30
  end
29
31
 
30
32
  def to_svg
31
- to_pdf.to_svg
32
- end
33
-
34
- def to_pdf
35
- pdf_content = GhostscriptWrapper.convert(content, eps_crop: false)
36
- pdf = Pdf.new(pdf_content)
37
- # Pass original BoundingBox dimensions to preserve them in conversions
38
- bbox = parse_bounding_box
39
- if bbox
40
- pdf.original_width = bbox[:urx] - bbox[:llx]
41
- pdf.original_height = bbox[:ury] - bbox[:lly]
42
- end
43
- pdf
33
+ Svg.from_content(Postsvg.convert(content))
44
34
  end
45
35
 
46
36
  def height
data/lib/vectory/svg.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "nokogiri"
4
+ require "postsvg"
4
5
 
5
6
  module Vectory
6
7
  class Svg < Vector
@@ -36,53 +37,43 @@ module Vectory
36
37
  end
37
38
 
38
39
  def to_eps
39
- InkscapeWrapper.convert(
40
- content: content,
41
- input_format: :svg,
42
- output_format: :eps,
43
- output_class: Eps,
44
- )
40
+ Eps.from_content(Postsvg.to_eps(content))
45
41
  end
46
42
 
47
43
  def to_ps
48
- InkscapeWrapper.convert(
49
- content: content,
50
- input_format: :svg,
51
- output_format: :ps,
52
- output_class: Ps,
53
- )
44
+ Ps.from_content(Postsvg.to_ps(content))
54
45
  end
55
46
 
56
47
  def height
57
- # Try to read height from SVG attributes first
58
- doc = Nokogiri::XML(content)
59
- svg_element = doc.at_xpath("//svg:svg",
60
- "svg" => SVG_NS) || doc.at_xpath("//svg")
61
-
62
- if svg_element && svg_element["height"]
63
- svg_element["height"].to_f.round
64
- else
65
- # Fall back to Inkscape query if no height attribute
66
- super
67
- end
48
+ dim_from_attr("height") || dim_from_viewbox(3) || super
68
49
  end
69
50
 
70
51
  def width
71
- # Try to read width from SVG attributes first
72
- doc = Nokogiri::XML(content)
73
- svg_element = doc.at_xpath("//svg:svg",
74
- "svg" => SVG_NS) || doc.at_xpath("//svg")
75
-
76
- if svg_element && svg_element["width"]
77
- svg_element["width"].to_f.round
78
- else
79
- # Fall back to Inkscape query if no width attribute
80
- super
81
- end
52
+ dim_from_attr("width") || dim_from_viewbox(2) || super
82
53
  end
83
54
 
84
55
  private
85
56
 
57
+ def svg_root
58
+ doc = Nokogiri::XML(content)
59
+ doc.at_xpath("//svg:svg", "svg" => SVG_NS) || doc.at_xpath("//svg")
60
+ end
61
+
62
+ def dim_from_attr(name)
63
+ value = svg_root&.[](name)
64
+ value&.to_f&.round
65
+ end
66
+
67
+ def dim_from_viewbox(index)
68
+ vb = svg_root&.[]("viewBox")
69
+ return nil unless vb
70
+
71
+ parts = vb.split
72
+ return nil unless parts.length == 4
73
+
74
+ parts[index].to_f.round
75
+ end
76
+
86
77
  def content=(content)
87
78
  # non-root node inserts the xml tag which breaks markup when placed in
88
79
  # another xml document
@@ -46,11 +46,15 @@ module Vectory
46
46
  end
47
47
 
48
48
  def height
49
- InkscapeWrapper.instance.height(content, self.class.default_extension)
49
+ raise Vectory::NotImplementedError,
50
+ "#height should be implemented in a subclass when no intrinsic " \
51
+ "dimension source is available."
50
52
  end
51
53
 
52
54
  def width
53
- InkscapeWrapper.instance.width(content, self.class.default_extension)
55
+ raise Vectory::NotImplementedError,
56
+ "#width should be implemented in a subclass when no intrinsic " \
57
+ "dimension source is available."
54
58
  end
55
59
 
56
60
  def to_uri
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Vectory
4
- VERSION = "0.10.1"
4
+ VERSION = "0.12.0"
5
5
  end
data/lib/vectory.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  # External dependencies
4
4
  require "logger"
5
- require "ukiryu"
6
5
 
7
6
  # Define base error class and additional error classes
8
7
  # (used in class bodies like cli.rb, so can't be autoloaded)
@@ -25,14 +24,6 @@ require_relative "vectory/version"
25
24
  module Vectory
26
25
  # Core utilities
27
26
  autoload :Utils, "vectory/utils"
28
- autoload :Platform, "vectory/platform"
29
-
30
- # Wrappers
31
- autoload :GhostscriptWrapper, "vectory/ghostscript_wrapper"
32
- autoload :InkscapeWrapper, "vectory/inkscape_wrapper"
33
-
34
- # Conversion system
35
- autoload :Conversion, "vectory/conversion"
36
27
 
37
28
  # Format classes
38
29
  autoload :Configuration, "vectory/configuration"
@@ -40,7 +31,6 @@ module Vectory
40
31
  autoload :ImageResize, "vectory/image_resize"
41
32
  autoload :Datauri, "vectory/datauri"
42
33
  autoload :Vector, "vectory/vector"
43
- autoload :Pdf, "vectory/pdf"
44
34
  autoload :Eps, "vectory/eps"
45
35
  autoload :Ps, "vectory/ps"
46
36
  autoload :Emf, "vectory/emf"
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # One-shot fixture regeneration script.
5
+ # Run from the vectory root: `bundle exec ruby scripts/regenerate_fixtures.rb`
6
+
7
+ require_relative "../lib/vectory"
8
+
9
+ Pairs = [
10
+ ["spec/examples/emf2eps/img.emf", :to_eps, "spec/examples/emf2eps/ref.eps"],
11
+ ["spec/examples/emf2ps/img.emf", :to_ps, "spec/examples/emf2ps/ref.ps"],
12
+ ["spec/examples/eps2emf/img.eps", :to_emf, "spec/examples/eps2emf/ref.emf"],
13
+ ["spec/examples/eps2ps/img.eps", :to_ps, "spec/examples/eps2ps/ref.ps"],
14
+ ["spec/examples/eps2svg/img.eps", :to_svg, "spec/examples/eps2svg/ref.svg"],
15
+ ["spec/examples/ps2emf/img.ps", :to_emf, "spec/examples/ps2emf/ref.emf"],
16
+ ["spec/examples/ps2eps/img.ps", :to_eps, "spec/examples/ps2eps/ref.eps"],
17
+ ["spec/examples/ps2svg/img.ps", :to_svg, "spec/examples/ps2svg/ref.svg"],
18
+ ["spec/examples/svg2emf/img.svg", :to_emf, "spec/examples/svg2emf/ref.emf"],
19
+ ["spec/examples/svg2eps/img.svg", :to_eps, "spec/examples/svg2eps/ref.eps"],
20
+ ["spec/examples/svg2ps/img.svg", :to_ps, "spec/examples/svg2ps/ref.ps"],
21
+ ].freeze
22
+
23
+ Pairs.each do |input, method, output|
24
+ ext = File.extname(input).delete(".")
25
+ klass_name = { "emf" => "Emf", "eps" => "Eps", "ps" => "Ps",
26
+ "svg" => "Svg" }.fetch(ext)
27
+ klass = Vectory.const_get(klass_name)
28
+ result = klass.from_path(input).public_send(method)
29
+ File.binwrite(output, result.content)
30
+ puts "[OK] #{input} -> #{output} (#{result.content.bytesize} bytes)"
31
+ rescue => e
32
+ puts "[FAIL] #{input} -> #{output}: #{e.class}: #{e.message}"
33
+ end
data/vectory.gemspec CHANGED
@@ -31,6 +31,6 @@ Gem::Specification.new do |spec|
31
31
  spec.add_dependency "image_size", ">= 3.2.0"
32
32
  spec.add_dependency "marcel", "~> 1.0"
33
33
  spec.add_dependency "nokogiri", "~> 1.14"
34
+ spec.add_dependency "postsvg", "~> 0.3"
34
35
  spec.add_dependency "thor", "~> 1.0"
35
- spec.add_dependency "ukiryu", "~> 0.3.0"
36
36
  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.10.1
4
+ version: 0.12.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: 2026-07-26 00:00:00.000000000 Z
11
+ date: 2026-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -87,33 +87,33 @@ dependencies:
87
87
  - !ruby/object:Gem::Version
88
88
  version: '1.14'
89
89
  - !ruby/object:Gem::Dependency
90
- name: thor
90
+ name: postsvg
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '1.0'
95
+ version: '0.3'
96
96
  type: :runtime
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '1.0'
102
+ version: '0.3'
103
103
  - !ruby/object:Gem::Dependency
104
- name: ukiryu
104
+ name: thor
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: 0.3.0
109
+ version: '1.0'
110
110
  type: :runtime
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: 0.3.0
116
+ version: '1.0'
117
117
  description: |
118
118
  Vectory performs pairwise vector image conversions for common
119
119
  vector image formats, such as SVG, EMF, EPS and PS.
@@ -158,21 +158,13 @@ files:
158
158
  - lib/vectory.rb
159
159
  - lib/vectory/cli.rb
160
160
  - lib/vectory/configuration.rb
161
- - lib/vectory/conversion.rb
162
- - lib/vectory/conversion/ghostscript_strategy.rb
163
- - lib/vectory/conversion/inkscape_strategy.rb
164
- - lib/vectory/conversion/strategy.rb
165
161
  - lib/vectory/datauri.rb
166
162
  - lib/vectory/emf.rb
167
163
  - lib/vectory/eps.rb
168
164
  - lib/vectory/errors.rb
169
165
  - lib/vectory/file_magic.rb
170
- - lib/vectory/ghostscript_wrapper.rb
171
166
  - lib/vectory/image.rb
172
167
  - lib/vectory/image_resize.rb
173
- - lib/vectory/inkscape_wrapper.rb
174
- - lib/vectory/pdf.rb
175
- - lib/vectory/platform.rb
176
168
  - lib/vectory/ps.rb
177
169
  - lib/vectory/svg.rb
178
170
  - lib/vectory/svg_document.rb
@@ -180,6 +172,7 @@ files:
180
172
  - lib/vectory/utils.rb
181
173
  - lib/vectory/vector.rb
182
174
  - lib/vectory/version.rb
175
+ - scripts/regenerate_fixtures.rb
183
176
  - tmp/.keep
184
177
  - vectory.gemspec
185
178
  homepage: https://github.com/metanorma/vectory