lib/vectory/svg.rb in vectory-0.2.0 vs lib/vectory/svg.rb in vectory-0.3.0
- old
+ new
@@ -1,27 +1,110 @@
# frozen_string_literal: true
+require "nokogiri"
+
module Vectory
class Svg < Vector
- SVG = { "m" => "http://www.w3.org/2000/svg" }.freeze
+ SVG_NS = "http://www.w3.org/2000/svg"
def self.default_extension
"svg"
end
def self.mimetype
"image/svg+xml"
end
+ def content
+ @document&.to_xml || @content
+ end
+
def to_emf
convert_with_inkscape("--export-type=emf", Emf)
end
def to_eps
convert_with_inkscape("--export-type=eps", Eps)
end
def to_ps
convert_with_inkscape("--export-type=ps", Ps)
+ end
+
+ def namespace(suffix, links, xpath_to_remove)
+ remap_links(links)
+ suffix_ids(suffix)
+ remove_xpath(xpath_to_remove)
+ end
+
+ def remap_links(map)
+ document.xpath(".//m:a", "m" => SVG_NS).each do |a|
+ href_attrs = ["xlink:href", "href"]
+ href_attrs.each do |p|
+ a[p] and x = map[File.expand_path(a[p])] and a[p] = x
+ end
+ end
+
+ self
+ end
+
+ def suffix_ids(suffix)
+ ids = collect_ids
+ return if ids.empty?
+
+ update_ids_attrs(ids, suffix)
+ update_ids_css(ids, suffix)
+
+ self
+ end
+
+ def remove_xpath(xpath)
+ document.xpath(xpath).remove
+
+ self
+ end
+
+ private
+
+ def content=(content)
+ if @document
+ @document = Nokogiri::XML(content)
+ else
+ @content = content
+ end
+ end
+
+ def document
+ @document ||= begin
+ doc = Nokogiri::XML(@content)
+ @content = nil
+ doc
+ end
+ end
+
+ def collect_ids
+ document.xpath("./@id | .//@id").map(&:value)
+ end
+
+ def update_ids_attrs(ids, suffix)
+ document.xpath(". | .//*[@*]").each do |a|
+ a.attribute_nodes.each do |x|
+ ids.include?(x.value) and x.value += sprintf("_%09d", suffix)
+ end
+ end
+ end
+
+ def update_ids_css(ids, suffix)
+ document.xpath("//m:style", "m" => SVG_NS).each do |s|
+ c = s.children.to_xml
+ ids.each do |i|
+ c = c.gsub(%r[##{i}\b],
+ sprintf("#%<id>s_%<suffix>09d", id: i, suffix: suffix))
+ .gsub(%r(\[id\s*=\s*['"]?#{i}['"]?\]),
+ sprintf("[id='%<id>s_%<suffix>09d']", id: i, suffix: suffix))
+ end
+
+ s.children = c
+ end
end
end
end