vectory 0.10.2 → 0.13.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: 50d97784f6629c9150bb2da21c151ba9f5a971e0c949bcb40c6f1e56a56a9e0c
4
- data.tar.gz: 1494199096329b53ec283fc424df6b49fcb1a0f95271b841e8289ee7d2e7fb49
3
+ metadata.gz: 66b15c386fa1dcdd0fc02473b9062f3eca19ed5b1bc40f2facec9577a4495fd4
4
+ data.tar.gz: d5bc9be14ab660ddbbba77548a205a472eb4215bb848c57d5e3d980205159da4
5
5
  SHA512:
6
- metadata.gz: 13129736f9ec596505e93e5e2b8904928be9dfb98ee9198259b34bdfecfdcbc2e0ca35e8e99133af06f9e65899434c55873f7bb5c94f42951360d13e6d812fc6
7
- data.tar.gz: 4daa37bcf802de4eaac71466694b229d6fee62e10b11237253f05a4e855da18b7646fcd14d4530ae8961ebf49b6cfcc60887b29761e4096ac65a885224fa9ec9
6
+ metadata.gz: 9e802267d5860c496738492218e4fd8260ff9c84546d63c11254d170f14ee1c8c9bebd24a943b24e8bcd5c7013db8a3d55844aba286d06f5959a717fe289da34
7
+ data.tar.gz: 53747660f38c403952debd623ad81dbce990e51fa8098d63480762c3de40531cc2602b903c943c91e01f9678433b6340b77529345ad487f53b4fb2c04ca4bfe6
data/Gemfile CHANGED
@@ -9,6 +9,7 @@ gem "canon", "~> 0.1.7"
9
9
  gem "connection_pool", "~> 2.0"
10
10
  gem "openssl", "~> 3.0"
11
11
  gem "rake"
12
+ gem "nokogiri" # dev-only: exercises SvgMapping's duck-typed document-object input (metanorma passes Nokogiri docs)
12
13
  gem "rspec"
13
14
  gem "rubocop"
14
15
  gem "rubocop-performance"
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
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
@@ -22,7 +22,7 @@ module Vectory
22
22
  end
23
23
 
24
24
  def to_ps
25
- to_pdf.to_ps
25
+ to_svg.to_ps
26
26
  end
27
27
 
28
28
  def to_svg
@@ -30,19 +30,7 @@ module Vectory
30
30
  end
31
31
 
32
32
  def to_emf
33
- to_pdf.to_emf
34
- end
35
-
36
- def to_pdf
37
- pdf_content = GhostscriptWrapper.convert(content, eps_crop: true)
38
- pdf = Pdf.new(pdf_content)
39
- # Pass original BoundingBox dimensions to preserve them in conversions
40
- bbox = parse_bounding_box
41
- if bbox
42
- pdf.original_width = bbox[:urx] - bbox[:llx]
43
- pdf.original_height = bbox[:ury] - bbox[:lly]
44
- end
45
- pdf
33
+ to_svg.to_emf
46
34
  end
47
35
 
48
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
@@ -22,29 +22,17 @@ module Vectory
22
22
  end
23
23
 
24
24
  def to_eps
25
- to_pdf.to_eps
25
+ to_svg.to_eps
26
26
  end
27
27
 
28
28
  def to_emf
29
- to_pdf.to_emf
29
+ to_svg.to_emf
30
30
  end
31
31
 
32
32
  def to_svg
33
33
  Svg.from_content(Postsvg.convert(content))
34
34
  end
35
35
 
36
- def to_pdf
37
- pdf_content = GhostscriptWrapper.convert(content, eps_crop: false)
38
- pdf = Pdf.new(pdf_content)
39
- # Pass original BoundingBox dimensions to preserve them in conversions
40
- bbox = parse_bounding_box
41
- if bbox
42
- pdf.original_width = bbox[:urx] - bbox[:llx]
43
- pdf.original_height = bbox[:ury] - bbox[:lly]
44
- end
45
- pdf
46
- end
47
-
48
36
  def height
49
37
  bbox = parse_bounding_box
50
38
  return super unless bbox
data/lib/vectory/svg.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "leptris"
4
+ require "postsvg"
4
5
 
5
6
  module Vectory
6
7
  class Svg < Vector
@@ -36,57 +37,51 @@ 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 = Leptris::XML.parse(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
89
- document = Nokogiri::XML(content).root
80
+ document = begin
81
+ Leptris::XML.parse(content).root
82
+ rescue Leptris::XML::ParseError
83
+ nil
84
+ end
90
85
  unless document
91
86
  raise ParsingError, "Could not parse '#{content&.slice(0, 30)}'"
92
87
  end
@@ -1,4 +1,4 @@
1
- require "nokogiri"
1
+ require "leptris"
2
2
 
3
3
  module Vectory
4
4
  # Represents and processes an SVG document within XML.
@@ -21,7 +21,7 @@ module Vectory
21
21
  class << self
22
22
  # Updates ID references in CSS style statements within a document.
23
23
  #
24
- # @param document [Nokogiri::XML::Document] The SVG document
24
+ # @param document [Leptris::XML::Document] The SVG document
25
25
  # @param ids [Array<String>] IDs to update
26
26
  # @param suffix [Integer, String] The suffix to apply (integers are zero-padded)
27
27
  # @return [void]
@@ -56,7 +56,7 @@ module Vectory
56
56
 
57
57
  # Updates ID attributes in SVG elements.
58
58
  #
59
- # @param document [Nokogiri::XML::Document] The SVG document
59
+ # @param document [Leptris::XML::Document] The SVG document
60
60
  # @param ids [Array<String>] IDs to update
61
61
  # @param suffix [Integer, String] The suffix to apply (integers are zero-padded)
62
62
  # @return [void]
@@ -76,7 +76,7 @@ module Vectory
76
76
  #
77
77
  # @param content [String] SVG XML content
78
78
  def initialize(content)
79
- @document = Nokogiri::XML(content)
79
+ @document = Leptris::XML.parse(content)
80
80
  end
81
81
 
82
82
  # Returns the processed SVG content as XML string.
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "leptris"
4
+
1
5
  module Vectory
2
6
  # Processes SVG mapping in XML documents.
3
7
  #
@@ -7,6 +11,11 @@ module Vectory
7
11
  # - Applying ID suffixes for uniqueness in multi-document scenarios
8
12
  # - Simplifying svgmap structure for final output
9
13
  #
14
+ # The document is processed on a leptris tree: pass XML content, or any
15
+ # document object responding to #to_xml (serialized once on entry).
16
+ # #call returns the processed Leptris document; callers working on
17
+ # their own DOM (e.g. Nokogiri) re-serialize and graft the result back.
18
+ #
10
19
  # == ID Suffixing
11
20
  #
12
21
  # SVG IDs are suffixed in two stages to ensure uniqueness:
@@ -30,7 +39,7 @@ module Vectory
30
39
  class SvgMapping
31
40
  # Namespace helper for XML namespace handling
32
41
  class Namespace
33
- # @param xmldoc [Nokogiri::XML::Document] The XML document
42
+ # @param xmldoc [Leptris::XML::Document] The XML document
34
43
  def initialize(xmldoc)
35
44
  @namespace = xmldoc.root.namespace
36
45
  end
@@ -61,7 +70,7 @@ module Vectory
61
70
  # @param path [String] Path to the XML file
62
71
  # @return [Vectory::SvgMapping] New mapping instance
63
72
  def self.from_path(path)
64
- new(Nokogiri::XML(File.read(path)))
73
+ new(File.read(path))
65
74
  end
66
75
 
67
76
  # Creates an SvgMapping from an XML string.
@@ -69,25 +78,27 @@ module Vectory
69
78
  # @param xml [String] XML content
70
79
  # @return [Vectory::SvgMapping] New mapping instance
71
80
  def self.from_xml(xml)
72
- new(Nokogiri::XML(xml))
81
+ new(xml)
73
82
  end
74
83
 
75
84
  # Initializes a new SvgMapping processor.
76
85
  #
77
- # @param doc [Nokogiri::XML::Document] The document containing svgmap elements
86
+ # @param doc [String, #to_xml] XML content, or a document object
87
+ # (serialized once on entry)
78
88
  # @param local_directory [String] Directory for resolving relative file paths
79
89
  # @param id_suffix [String, nil] Optional suffix derived from document/container
80
90
  # identity. Applied before the index suffix to provide cross-document
81
91
  # uniqueness. Example: "_ISO_17301-1_2016"
82
92
  def initialize(doc, local_directory = "", id_suffix: nil)
83
- @doc = doc
93
+ xml = doc.respond_to?(:to_xml) ? doc.to_xml : doc
94
+ @doc = Leptris::XML.parse(xml)
84
95
  @local_directory = local_directory
85
96
  @id_suffix = id_suffix
86
97
  end
87
98
 
88
99
  # Processes all svgmap elements in the document.
89
100
  #
90
- # @return [Nokogiri::XML::Document] The processed document
101
+ # @return [Leptris::XML::Document] The processed document
91
102
  def call
92
103
  @namespace = Namespace.new(@doc)
93
104
 
@@ -109,7 +120,7 @@ module Vectory
109
120
 
110
121
  # Processes a single svgmap element.
111
122
  #
112
- # @param svgmap [Nokogiri::XML::Element] The svgmap element to process
123
+ # @param svgmap [Leptris::XML::Element] The svgmap element to process
113
124
  # @param index [Integer] Position of this svgmap in the document (0-indexed)
114
125
  def process_svgmap(svgmap, index)
115
126
  image = extract_image_tag(svgmap)
@@ -125,19 +136,19 @@ module Vectory
125
136
 
126
137
  # Extracts the image element (SVG inline or image with src) from svgmap.
127
138
  #
128
- # @param svgmap [Nokogiri::XML::Element] The svgmap element
129
- # @return [Nokogiri::XML::Element, nil] The image/svg element or nil
139
+ # @param svgmap [Leptris::XML::Element] The svgmap element
140
+ # @return [Leptris::XML::Element, nil] The image/svg element or nil
130
141
  def extract_image_tag(svgmap)
131
- image = svgmap.at(@namespace.ns(".//image"))
142
+ image = svgmap.at_xpath(@namespace.ns(".//image"))
132
143
  return image if image && image["src"] && !image["src"].empty?
133
144
 
134
- svgmap.at(".//m:svg", "m" => SVG_NS)
145
+ svgmap.at_xpath(".//m:svg", "m" => SVG_NS)
135
146
  end
136
147
 
137
148
  # Generates processed SVG content for an svgmap.
138
149
  #
139
- # @param image [Nokogiri::XML::Element] The image/svg element
140
- # @param svgmap [Nokogiri::XML::Element] The parent svgmap element
150
+ # @param image [Leptris::XML::Element] The image/svg element
151
+ # @param svgmap [Leptris::XML::Element] The parent svgmap element
141
152
  # @param index [Integer] Index suffix to apply
142
153
  # @return [String, nil] Processed SVG content or nil if invalid
143
154
  def generate_content(image, svgmap, index)
@@ -153,7 +164,7 @@ module Vectory
153
164
 
154
165
  # Builds an SvgDocument from an image element.
155
166
  #
156
- # @param image [Nokogiri::XML::Element] The image element
167
+ # @param image [Leptris::XML::Element] The image element
157
168
  # @return [Vectory::SvgDocument, nil] The SVG document or nil if invalid
158
169
  def build_svg_document(image)
159
170
  vector = build_vector(image)
@@ -164,7 +175,7 @@ module Vectory
164
175
 
165
176
  # Builds a Vector from an image element.
166
177
  #
167
- # @param image [Nokogiri::XML::Element] The image element
178
+ # @param image [Leptris::XML::Element] The image element
168
179
  # @return [Vectory::Vector, nil] The vector or nil if invalid
169
180
  def build_vector(image)
170
181
  return Vectory::Svg.from_content(image.to_xml) if image.name == "svg"
@@ -182,7 +193,7 @@ module Vectory
182
193
 
183
194
  # Builds a mapping from target hrefs to their link targets.
184
195
  #
185
- # @param svgmap [Nokogiri::XML::Element] The svgmap element
196
+ # @param svgmap [Leptris::XML::Element] The svgmap element
186
197
  # @return [Hash{String => String}] Mapping of href to target
187
198
  def from_targets_to_links_map(svgmap)
188
199
  targets = svgmap.xpath(@namespace.ns("./target"))
@@ -199,13 +210,13 @@ module Vectory
199
210
 
200
211
  # Extracts link target from a target element.
201
212
  #
202
- # @param target_tag [Nokogiri::XML::Element] The target element
213
+ # @param target_tag [Leptris::XML::Element] The target element
203
214
  # @return [String, nil] The link target or nil
204
215
  def link_target(target_tag)
205
- xref = target_tag.at(@namespace.ns("./xref"))
216
+ xref = target_tag.at_xpath(@namespace.ns("./xref"))
206
217
  return "##{xref['target']}" if xref
207
218
 
208
- link = target_tag.at(@namespace.ns("./link"))
219
+ link = target_tag.at_xpath(@namespace.ns("./link"))
209
220
  return unless link
210
221
 
211
222
  link["target"]
@@ -214,11 +225,11 @@ module Vectory
214
225
  # Simplifies svgmap after processing.
215
226
  # Removes svgmap wrapper if no more target elements with eref.
216
227
  #
217
- # @param svgmap [Nokogiri::XML::Element] The svgmap element
228
+ # @param svgmap [Leptris::XML::Element] The svgmap element
218
229
  def simplify_svgmap(svgmap)
219
- return if svgmap.at(@namespace.ns("./target/eref"))
230
+ return if svgmap.at_xpath(@namespace.ns("./target/eref"))
220
231
 
221
- svgmap.replace(svgmap.at(@namespace.ns("./figure")))
232
+ svgmap.replace(svgmap.at_xpath(@namespace.ns("./figure")))
222
233
  end
223
234
  end
224
235
  end
@@ -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.2"
4
+ VERSION = "0.13.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
@@ -30,8 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_dependency "emfsvg", "~> 0.1", ">= 0.1.2"
31
31
  spec.add_dependency "image_size", ">= 3.2.0"
32
32
  spec.add_dependency "marcel", "~> 1.0"
33
- spec.add_dependency "nokogiri", "~> 1.14"
34
- spec.add_dependency "postsvg", "~> 0.1"
33
+ spec.add_dependency "leptris", "~> 1.9.361.1"
34
+ spec.add_dependency "postsvg", "~> 0.3"
35
35
  spec.add_dependency "thor", "~> 1.0"
36
- spec.add_dependency "ukiryu", "~> 0.3.0"
37
36
  end