Purpose
Vectory is a Ruby gem that performs pairwise vector image conversions for common vector image formats (EPS, PS, EMF, SVG).
Vectory shall give you a glorious vectory over EPS files.
Installation
Prerequisites
Vectory relies on the following software to be installed:
|
Note
|
Inkscape 1.3.1+ does not work properly with EPS/PS on Windows. To avoid this issue, the 1.3.0 version of Inkscape can be used. |
Gem install
gem install vectory
Or include it in your gemspec.
Usage
$ vectory [-o {output-file-name}] -f {format} {input-file-name}
Where,
format-
the desired output format (one of:
svg,eps,ps,emf) input-file-name-
file path to the input file
output-file-name-
file path to the desired output file (with the file extension) (default: writes to a current directory by the input filename with an extension changed to a desired format)
Using the Ruby library
Some examples:
Take EMF as a path to a file and return SVG as a string:
Take EPS as a string and return EMF as a path to a file:
# NOTE: content is shortened for readability
content = "%!PS-Adobe-3.0 EPSF-3.0\n ... %%Trailer"
Vectory::Eps.from_content(content).to_emf.write.path
Take SVG as a datauri and return EMF as a datauri:
What is supported?
There are several vector classes which support conversion between each other:
Each of them can be instantiated in several ways:
Vectory::Eps.from_path("images/img.eps")
Vectory::Eps.from_content("%!PS-Adobe-3.0...")
Vectory::Eps.from_datauri("data:image/svg+xml;base64,PHN2 ... 2Zz4=")
Vectory::Eps.from_node(Nokogiri::XML(
"<image mimetype="application/postscript" alt="3">
%!PS-Adobe-3.0 EPSF-3.0 ...
</image>"
).child)
Converting to other formats:
Vectory::Eps.from_content(content).to_ps
Vectory::Eps.from_content(content).to_emf
Vectory::Eps.from_content(content).to_svg
Several ways of getting content of an object:
Vectory::Eps.from_content(content).to_svg.content
Vectory::Eps.from_content(content).to_svg.to_uri.content # as datauri
Vectory::Eps.from_content(content).to_svg.write.path
Datauri
Also there is the Vectory::Datauri class which represents vectory images in
the datauri format.
Convert an SVG datauri to a plain SVG:
Convert an EPS file to its datauri representation:
There is also a simplified API for this case:
SVG mapping (for the metanorma project)
Vectory can integrate SVG files into XML or HTML, respecting internal id and link references. It supports ID disambiguation for multi-document and multi-svgmap scenarios.
Basic usage
xml_string = Vectory::SvgMapping.from_path("doc.xml").to_xml
ID suffixing for uniqueness
When processing multiple documents or multiple svgmaps within a document, SVG IDs must be unique to avoid conflicts. Vectory applies two types of suffixes:
- ID suffix (Cross-document uniqueness)
-
An optional suffix derived from document or container identity (e.g.,
_ISO_17301-1_2016). This provides uniqueness across documents or collections. - Index suffix (Multi-svgmap uniqueness)
-
Automatically applied based on the svgmap’s position in the document (0, 1, 2, …). Formatted as a 9-digit zero-padded number (e.g.,
_000000000,_000000001). This provides uniqueness when a document contains multiple svgmaps.
Original ID: fig1
With ID suffix only: fig1_ISO_17301-1_2016
With both suffixes: fig1_ISO_17301-1_2016_000000000
Usage with ID suffix
mapping = Vectory::SvgMapping.new(doc, "", id_suffix: "_ISO_17301-1_2016")
xml_string = mapping.call.to_xml
Input format
The input XML must support the svgmap tag with link mapping.
<svgmap id="_4072bdcb-5895-4821-b636-5795b96787cb">
<figure><image src="action_schemaexpg1.svg"/></figure>
<target href="mn://action_schema">
<xref target="ref1">Computer</xref>
</target>
<target href="http://www.example.com">
<link target="http://www.example.com">Phone</link>
</target>
</svgmap>
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
#Layer_1 { fill:none }
svg[id = 'Layer_1'] { fill:none }
.st0{fill:none;stroke:#000000;stroke-miterlimit:10;}
</style>
<a xlink:href="mn://action_schema" xlink:dummy="Layer_1">
<rect x="123.28" y="273.93" class="st0" width="88.05" height="41.84"/>
</a>
<a xlink:href="mn://basic_attribute_schema" >
<rect x="324.69" y="450.52" class="st0" width="132.62" height="40.75"/>
</a>
<a xlink:href="mn://support_resource_schema" >
<rect x="324.69" y="528.36" class="st0" width="148.16" height="40.75"/>
</a>
</svg>
Output format
<figure>
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1'
id='Layer_1_000000001' x='0px' y='0px' viewBox='0 0 595.28 841.89'>
<style> #Layer_1_000000001 { fill:none }</style>
<a xlink:href='#ref1' xlink:dummy='Layer_1_000000001'>
<rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
</a>
<a xlink:href='mn://basic_attribute_schema'>
<rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
</a>
<a xlink:href='mn://support_resource_schema'>
<rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
</a>
</svg>
</figure>
Inline SVG support
SVG can also be provided inline within the svgmap:
<svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
<figure>
<svg xmlns='http://www.w3.org/2000/svg' id='Layer_1'>
<a href="mn://action_schema">
<rect x="123.28" y="273.93" class="st0"/>
</a>
</svg>
</figure>
<target href="mn://action_schema">
<xref target="ref1">Computer</xref>
</target>
</svgmap>
Data URI support
Images can be provided as data URIs:
<svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
<figure>
<image src='data:image/svg+xml;base64,PD94...'/>
</figure>
<target href="href1.htm">
<xref target="ref1">Computer</xref>
</target>
</svgmap>
File system operations
An image object contains information where it is written. It can be obtained
with the #path API:
Before the first write it raises the NotWrittenToDiskError error:
vector.path # => raise NotWrittenToDiskError
After writing it returns a path of the image on a disk:
vector.write
vector.path # => "/tmp/xxx/yyy"
By default it writes to a temporary directory but it can be changed by providing an argument with a desired path:
vector.write("images/img.eps")
vector.path # => "images/img.eps"
Since an image can be initially read from a disk, it also keeps an initial path. To avoid accidental overwrite, this path is used only for read-only purposes.
vector.initial_path # => "storage/images/img.eps"
Additional properties
The following additional properties are supported:
Datauri#mime
Datauri#height
Datauri#width
Vector (Eps, Ps, Svg, Emf)
Vector#mime
Vector#size
Vector#file_size
Vector#height
Vector#width
Development
Regenerating test fixtures
Some test fixtures are generated by external tools (Ghostscript, Inkscape, cairo). When these tools are updated, the reference files may need to be regenerated.
To regenerate all test fixtures:
bundle exec rake regenerate_fixtures
This will update the following files:
-
spec/examples/ps2eps/ref.eps- PS to EPS conversion reference -
spec/examples/ps2svg/ref.svg- PS to SVG conversion reference -
spec/examples/svg/doc2-ref.xml- SVG mapping reference
|
Note
|
After regenerating fixtures, review the changes to ensure they are expected before committing. |
Releasing
Releasing is done automatically with GitHub Actions. Just bump and tag with
gem-release.
For a patch release (0.0.x) use:
gem bump --version patch --tag --push
For a minor release (0.x.0) use:
gem bump --version minor --tag --push
Contributing
Bug reports and pull requests are welcome on GitHub at: