Gem Version rake Code Climate Pull Requests Commits since latest

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:

path = "path/to/file.emf"

Vectory::Emf.from_path(path).to_svg.content

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:

# NOTE: datauri is shortened for readability
uri = "data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0 ... GRkYiLz48L3N2Zz4="

Vectory::Datauri.new(uri).to_vector.to_emf.to_uri.content

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:

# NOTE: datauri is shortened for readability
uri = "data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0 ... GRkYiLz48L3N2Zz4="
Vectory::Datauri.new(uri).to_vector.content

Convert an EPS file to its datauri representation:

eps = Vectory::Eps.from_path("img.eps")
Vectory::Datauri.from_vector(eps).content

There is also a simplified API for this case:

Vectory::Eps.from_path("img.eps").to_uri.content

SVG mapping (for the metanorma project)

Vectory can integrate SVG files into XML or HTML, respecting internal id and link references:

xml_string = Vectory::SvgMapping.from_path("doc.xml").to_xml

In order to do that an initial XML should support the svgmap tag with links mapping. For example, it can convert XML like this:

<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>
action_schemaexpg1.svg
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 595.28 841.89" style="enable-background:new 0 0 595.28 841.89;" xml:space="preserve">
  <style type="text/css">
          #Layer_1 { fill:none }
          svg[id = 'Layer_1'] { fill:none }
    .st0{fill:none;stroke:#000000;stroke-miterlimit:10;}
  </style>
  <image style="overflow:visible;" width="368" height="315" xlink:href="data:image/gif;base64,R0lG..ommited to save space" transform="matrix(1 0 0 1 114 263.8898)">
  </image>
  <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>

into XML containing inline SVG tags. Notice changes in the id attributes and the a tags:

<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='enable-background:new 0 0 595.28 841.89;' xml:space='preserve'>
    <style> ..ommited to save space </style>
    <image> ..ommited </image>
    <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>

It also supports SVG in a form of an inline tag:

<svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
  <figure>
    <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' viewBox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve'>
      <a href="mn://action_schema" >
        <rect x="123.28" y="273.93" class="st0" width="88.05" height="41.84"/>
      </a>
      <a 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>
  <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>

and datauri:

<svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
  <figure>
    <image src='data:image/svg+xml;base64,PD94..ommited to save space' id='__ISO_17301-1_2016' mimetype='image/svg+xml' height='auto' width='auto' alt='Workmap1'/>
  </figure>
  <target href="href1.htm">
    <xref target="ref1">Computer</xref>
  </target>
  <target href="mn://basic_attribute_schema">
    <link target="http://www.example.com">Phone</link>
  </target>
  <target href="mn://support_resource_schema">
    <eref type="express" bibitemid="express_action_schema" citeas="">
      <localityStack><locality type="anchor"><referenceFrom>action_schema.basic</referenceFrom></locality></localityStack>
      Coffee
    </eref>
  </target>
</svgmap>

File system operations

An image object contains information where it is written. It can be obtained with the #path API:

vector = Vectory::Eps.from_path("img.eps")
vector.path

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

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: