Class: Voltron::Svg::Tag

Inherits:
Object
  • Object
show all
Includes:
ActionView::Helpers
Defined in:
lib/voltron/svg/tag.rb

Instance Method Summary collapse

Constructor Details

#initialize(file, options = {}) ⇒ Tag

Returns a new instance of Tag.



9
10
11
12
13
14
# File 'lib/voltron/svg/tag.rb', line 9

def initialize(file, options={})
  options = options.symbolize_keys
  @file = file
  @options = options
  setup
end

Instance Method Details

#asset_path(filename) ⇒ Object



39
40
41
42
43
44
45
# File 'lib/voltron/svg/tag.rb', line 39

def asset_path(filename)
  if Rails.application.config.assets.digest && Rails.application.config.assets.compile
    filename = Rails.application.assets.find_asset(filename).try(:digest_path) || filename
  end

  File.join(Rails.application.config.assets.prefix, filename)
end

#attributesObject



52
53
54
55
56
57
# File 'lib/voltron/svg/tag.rb', line 52

def attributes
  @options[:alt] ||= @file
  @options[:data] ||= {}
  @options[:data].merge!({ svg: true, size: size, fallback: image_path })
  @options.reject { |k,v| [:color, :fallback, :quality, :extension].include?(k) }
end

#colorObject

Get the color specified, if any, removing anything that’s not alphanumeric for use in the generated filename



80
81
82
# File 'lib/voltron/svg/tag.rb', line 80

def color
  @options[:color].to_s.gsub(/[^\dA-Z]/i, "")
end

#create_pngObject

If we haven’t done so already, create the PNG from the SVG source file



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/voltron/svg/tag.rb', line 146

def create_png
  return false if File.exists?(fallback_path)

  begin
    # Ensure the SVG we will convert to a PNG exists first
    create_svg

    # Then convert the SVG to a PNG
    ::MiniMagick::Tool::Convert.new do |convert|
      convert.merge! ["-gravity", "center"]
      convert.merge! ["-background", "none"]
      convert.merge! ["-quality", @options[:quality]]
      convert.merge! ["-density", density]
      convert.merge! ["-resize", size]
      convert.merge! ["-extent", size]
      convert << to_svg_path
      convert << fallback_path
      convert
    end

    Rails.application.assets_manifest.compile name(:png, size.to_s.downcase, color.upcase)

    Voltron.log "Generated PNG: #{app_path(to_svg_path)} -> #{app_path(fallback_path)}", "SVG", :light_magenta
    true
  rescue ::MiniMagick::Error => e
    Voltron.log e.message, "SVG", :red
    false
  end
end

#create_svgObject

If a color is specified and we haven’t already created the colorized SVG, generate it



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/voltron/svg/tag.rb', line 127

def create_svg
  if !color.blank? && !File.exists?(to_svg_path)
    # Get the svg contents
    content = File.read(from_svg_path)

    # Set the color of any path/stroke in the svg
    content.gsub! /fill=\"[^\"]+\"/, "fill=\"#{@options[:color]}\""
    content.gsub! /stroke=\"[^\"]+\"/, "stroke=\"#{@options[:color]}\""

    # Write the new svg file
    File.open(to_svg_path, "w") { |f| f.puts content }

    Rails.application.assets_manifest.compile name(:svg, color.upcase)

    Voltron.log "Generated SVG: #{app_path(from_svg_path)} -> #{app_path(to_svg_path)}", "SVG", :light_magenta
  end
end

#fallback_pathObject

The fallback image path for the SVG



112
113
114
# File 'lib/voltron/svg/tag.rb', line 112

def fallback_path
  File.join Voltron.config.svg.image_directory, name(:png, size.to_s.downcase, color.upcase)
end

#from_svg_pathObject

The source SVG path



117
118
119
# File 'lib/voltron/svg/tag.rb', line 117

def from_svg_path
  File.join Voltron.config.svg.source_directory, name(@options[:extension])
end

#heightObject

Attempt to get height from specified options, then from the source SVG file itself, and ultimately say the height is 16



75
76
77
# File 'lib/voltron/svg/tag.rb', line 75

def height
  (@options[:height] || svg.try(:height) || 16).to_i
end

#htmlObject

Return the html <img /> tag with the needed attributes



48
49
50
# File 'lib/voltron/svg/tag.rb', line 48

def html
  image_tag svg_path, attributes
end

#image_pathObject



30
31
32
33
# File 'lib/voltron/svg/tag.rb', line 30

def image_path
  # Get the fallback image path, either using the :fallback option if specified, or use the default generated png
  asset_path (@options[:fallback] || name(:png, size.to_s.downcase, color.upcase))
end

#name(extension = nil, *opts) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/voltron/svg/tag.rb', line 88

def name(extension = nil, *opts)
  filename = @file.to_s

  if extension.nil? && (matches = filename.match(/\.(.*)$/i))
    extension = matches[1]
  end

  # If called like `svg_tag :my_icon`, convert to "my-icon"
  # If the filename "my_icon" is actually needed, call `svg_tag "my_icon"` (don't use symbol)
  filename = filename.dasherize if @file.is_a?(Symbol)

  pieces = filename.split(".").insert(1, opts).flatten

  # Add the extension if it doesn't end with the extension, if nil it will just get removed on the next line
  pieces << extension unless pieces[-1] == extension.to_s

  # Remove anything that might be empty or nil
  pieces.reject!(&:blank?)

  # Put all the pieces together, get a name like file.50x50.RED.png
  pieces.join(".")
end

#setupObject



16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/voltron/svg/tag.rb', line 16

def setup
  # If a size is specified, extract it's width/height
  @options[:width], @options[:height] = extract_dimensions(@options.delete(:size)) if @options[:size]

  # Ensure the svg extension is added if a symbol was provided for icon name
  @options[:extension] ||= :svg if @file.is_a?(Symbol)

  # Set the default quality
  @options[:quality] ||= Voltron.config.svg.quality

  # Generate the SVG (if custom color) and the corresponding fallback PNG, only if running in environment that allows conversion
  create_png if Voltron.config.svg.buildable?
end

#sizeObject



84
85
86
# File 'lib/voltron/svg/tag.rb', line 84

def size
  "#{width}x#{height}"
end

#svgObject

Try to get the SVG file



60
61
62
63
64
65
66
67
# File 'lib/voltron/svg/tag.rb', line 60

def svg
  begin
    @svg ||= ::MiniMagick::Image.open(to_svg_path)
  rescue ::MiniMagick::Error => e
  rescue ::Errno::ENOENT => e
    false
  end
end

#svg_pathObject



35
36
37
# File 'lib/voltron/svg/tag.rb', line 35

def svg_path
  asset_path name(@options[:extension], color.upcase)
end

#to_svg_pathObject

The SVG we’ll ultimately use to generate the PNG, if no color was specified this will be the same as ‘from_svg_path`



122
123
124
# File 'lib/voltron/svg/tag.rb', line 122

def to_svg_path
  File.join Voltron.config.svg.source_directory, name(@options[:extension], color.upcase)
end

#widthObject

Attempt to get width from specified options, then from the source SVG file itself, and ultimately say the width is 16



70
71
72
# File 'lib/voltron/svg/tag.rb', line 70

def width
  (@options[:width] || svg.try(:width) || 16).to_i
end