lib/esvg/symbol.rb in esvg-4.3.0 vs lib/esvg/symbol.rb in esvg-4.3.1

- old
+ new

@@ -1,10 +1,10 @@ require 'open3' module Esvg class Symbol - attr_reader :name, :id, :path, :content, :optimized, :size, :group, :mtime + attr_reader :name, :id, :path, :content, :optimized, :size, :group, :mtime, :defs include Esvg::Utils def initialize(path, config={}) @config = config @@ -15,29 +15,28 @@ def read return if !File.exist?(@path) time = last_modified - if @mtime != time - @mtime = time - @content = pre_optimize File.read(@path) - @size = dimensions - @optimized = nil - @optimized_at = nil - end # Ensure that cache optimization matches current optimization settings # If config has changed name, reset optimized build (name gets baked in) - if @svgo_optimized != svgo? || name != file_name + if @mtime != time || @svgo_optimized != svgo? || name != file_name @optimized = nil @optimized_at = nil end - + @group = dir_key @name = file_name @id = file_id file_key + if @mtime != time + @content = prep_defs pre_optimize File.read(@path) + @mtime = time + @size = dimensions + end + self end def width @size[:width] @@ -54,10 +53,11 @@ name: @name, group: @group, mtime: @mtime, size: @size, content: @content, + defs: @defs, optimized: @optimized, optimized_at: @optimized_at, svgo_optimized: svgo? && @svgo_optimized } end @@ -136,12 +136,10 @@ def optimize # Only optimize again if the file has changed return @optimized if @optimized && @optimized_at > @mtime @optimized = @content - sub_def_ids - move_defs if svgo? response = Open3.capture3(%Q{#{Esvg.node_module('svgo')} --disable=removeUselessDefs -s '#{@optimized}' -o -}) if !response[0].empty? && response[2].success? @optimized = response[0] @@ -225,10 +223,11 @@ {} end end def pre_optimize(svg) + # Generate a regex of attributes to be removed att = Regexp.new %w(xmlns xmlns:xlink xml:space version).map { |m| "#{m}=\".+?\"" }.join('|') svg.strip .gsub(att, '') # Remove unwanted attributes @@ -242,11 +241,10 @@ end def post_optimize @optimized = set_attributes .gsub(/<\/svg/,'</symbol') # Replace svgs with symbols - .gsub(/class="def-/,'id="def-') # Replace <def> classes with ids (classes are generated in sub_def_ids) .gsub(/\w+=""/,'') # Remove empty attributes end def set_attributes attr.keys.each do |key| @@ -259,38 +257,30 @@ # Scans <def> blocks for IDs # If urls(#id) are used, ensure these IDs are unique to this file # Only replace IDs if urls exist to avoid replacing defs # used in other svg files # - def sub_def_ids - @optimized.scan(/<defs>.+<\/defs>/m).flatten.each do |defs| - defs.scan(/id="(.+?)"/).flatten.uniq.each_with_index do |id, index| + def prep_defs(svg) - # If there are urls which refer to - # ids be sure to update both - # - if @optimized.match(/url\(##{id}\)/) - new_id = "def-#{@id}-#{index}" + # <defs> should be moved to the beginning of the SVG file for braod browser support. Ahem, Firefox ಠ_ಠ + # When symbols are reassembled, @defs will be added back + + if @defs = svg.scan(/<defs>(.+)<\/defs>/m).flatten[0] + svg.sub!("<defs>#{@defs}</defs>", '') + @defs.gsub!(/(\n|\s{2,})/,'') - @optimized = @optimized.gsub(/id="#{id}"/, %Q{class="#{new_id}"}) - .gsub(/url\(##{id}\)/, "url(##{new_id})") + @defs.scan(/id="(.+?)"/).flatten.uniq.each_with_index do |id, index| - # Otherwise just leave the IDs of the - # defs and change them to classes to - # avoid SVGO ID mangling - # - else - @optimized = @optimized.gsub /id="#{id}"/, %Q{class="#{id}"} + # If there are urls matching def ids + if svg.match(/url\(##{id}\)/) + + new_id = "def-#{@id}-#{index}" # Generate a unique id + @defs.gsub!(/id="#{id}"/, %Q{id="#{new_id}"}) # Replace the def ids + svg.gsub!(/url\(##{id}\)/, "url(##{new_id})") # Replace url references to these old def ids end end end - end - # <defs> should be moved to the beginning of the SVG file for braod browser support. Ahem, Firefox ಠ_ಠ - def move_defs - if defs = @optimized.scan(/(\s*<defs>.+<\/defs>\s*)/m).flatten[0] - @optimized.sub!(defs, '') - @optimized.sub!(/(<svg.+?>)/, "\1#{defs}") - end + svg end end end