module Sass::Script::Functions

Public Instance Methods

svg_template(path, variables = {}) click to toggle source
# File lib/svg-templates/sass_extensions.rb, line 16
def svg_template(path, variables = {})
  real_path = File.join(Compass.configuration.images_path, path.value)

  # Process SVG
  data = read_svg_file(real_path)
  data = replace_svg_variables(data, variables)

  # Generate filename
  css_basepath = Pathname.new(options[:css_filename].to_s).dirname.sub_ext('').to_s
  css_filename = Pathname.new(options[:css_filename].to_s).basename.sub_ext('').to_s
  svg_filename = Pathname.new(real_path).basename.sub_ext('').to_s
  hash         = Digest::MD5.hexdigest(data)[0, 5]
  svg_basename = "#{css_filename}-#{svg_filename}.#{hash}.svg"
  svg_pathname = css_basepath + '/' + svg_basename

  unless File.exist?(svg_pathname)
    # Write SVG image file
    File.write(svg_pathname, minify_svg_data(data))
  end
  
  url = handle_cache_buster(svg_basename, hash)
  unquoted_string("url('#{url}')")
end
svg_template_inline(path, variables = {}) click to toggle source
# File lib/svg-templates/sass_extensions.rb, line 40
def svg_template_inline(path, variables = {})
  real_path = File.join(Compass.configuration.images_path, path.value)

  # Process SVG
  data = read_svg_file(real_path)
  data = replace_svg_variables(data, variables)
  data = minify_svg_data(data)

  # Inline SVG image
  data = [data].flatten.pack('m').gsub("\n", '')
  url = "data:image/svg+xml;base64,#{data}"
  unquoted_string("url('#{url}')")
end
svg_template_png(path, variables = {}) click to toggle source
# File lib/svg-templates/sass_extensions.rb, line 54
def svg_template_png(path, variables = {})
  real_path = File.join(Compass.configuration.images_path, path.value)

  # Process SVG
  data = read_svg_file(real_path)
  data = replace_svg_variables(data, variables)

  # Generate filename
  css_basepath = Pathname.new(options[:css_filename].to_s).dirname.sub_ext('').to_s
  css_filename = Pathname.new(options[:css_filename].to_s).basename.sub_ext('').to_s
  svg_filename = Pathname.new(real_path).basename.sub_ext('').to_s
  hash         = Digest::MD5.hexdigest(data)[0, 5]
  png_basename = "#{css_filename}-#{svg_filename}.#{hash}.png"
  png_pathname = css_basepath + '/' + png_basename

  unless File.exist?(png_pathname)
    # Render SVG as PNG image file using ImageMagick
    img = load_svg_image_data(data)
    img.write(png_pathname)
  end
  
  url = handle_cache_buster(png_basename, hash)
  unquoted_string("url('#{url}')")
end
svg_template_png_inline(path, variables = {}) click to toggle source
# File lib/svg-templates/sass_extensions.rb, line 79
def svg_template_png_inline(path, variables = {})
  real_path = File.join(Compass.configuration.images_path, path.value)

  # Process SVG
  data = read_svg_file(real_path)
  data = replace_svg_variables(data, variables)

  # Render SVG as PNG image file using ImageMagick
  img = load_svg_image_data(data)
  data = img.to_blob()

  # Inline SVG image
  data = [data].flatten.pack('m').gsub("\n", '')
  url = "data:image/svg+xml;base64,#{data}"
  unquoted_string("url('#{url}')")
end

Private Instance Methods

get_config_setting(name, default = nil) click to toggle source
# File lib/svg-templates/sass_extensions.rb, line 98
def get_config_setting(name, default = nil)
  # Read config setting from a scoped or global variable
  setting = environment.caller.var(name)
  if setting.nil?
    default
  else
    setting.value
  end
end
handle_cache_buster(url, hash) click to toggle source
# File lib/svg-templates/sass_extensions.rb, line 162
def handle_cache_buster(url, hash)
  cache_buster = get_config_setting('svg-templates-cache-buster', 'auto')
  cache_buster = hash if cache_buster == 'auto'
  cache_buster.to_s.length > 0 ? url + '?' + cache_buster.to_s : url
end
load_svg_image_data(data) click to toggle source
# File lib/svg-templates/sass_extensions.rb, line 147
def load_svg_image_data(data)
  begin
    require 'RMagick'
  rescue LoadError
    raise Compass::Error, "Please install RMagick to make use of the PNG rendering functionality."
  end
  begin
    img = Magick::Image.from_blob(data).first
    # Strip and suppress any color profiles (gamma correction etc.)
    img.strip!
  rescue
    raise Compass::Error, "SVG file #{real_path} cannot be processed - probably invalid?"
  end
end
minify_svg_data(data) click to toggle source
# File lib/svg-templates/sass_extensions.rb, line 132
def minify_svg_data(data)
  if get_config_setting('svg-templates-minify', 1) == 1
    # Strip XML prolog, as browsers don't need it when a MIME type is specified
    data = data.gsub(/^<\?xml\s.+?\?>/, '')
    # Strip doctype
    data = data.gsub(/^<!DOCTYPE\s.+?>/, '')
    # Strip comments
    data = data.gsub(/<!--.*?-->/, '')
    # Compress consecutive whitespace
    data = data.gsub(/[\s\r\n]+/, ' ')
  else
    data
  end
end
read_svg_file(real_path) click to toggle source
# File lib/svg-templates/sass_extensions.rb, line 108
def read_svg_file(real_path)
  if File.readable?(real_path)
    File.open(real_path, "rb") {|io| io.read}
  else
    raise Compass::Error, "File not found or cannot be read: #{real_path}"
  end
end
replace_svg_variables(data, variables) click to toggle source
# File lib/svg-templates/sass_extensions.rb, line 116
def replace_svg_variables(data, variables)
  # Cast Sass map to hash
  if variables.respond_to?(:to_h)
    variables = variables.to_h
  end

  # Replace variables
  variables.each do |key, value|
    escaped_key = Regexp.escape(key.to_s)
    data = data.gsub(/#\{\$#{escaped_key}(?:\|\|(.+?))?\}/, value.to_s)
  end

  # Replace undefined variables by their defaults or strip them entirely
  data.gsub(/#\{\$[a-z_][a-zA-Z0-9_]*(?:\|\|(.+?))?\}/, '\1')
end