inline_svg-1.10.0/0000755000004100000410000000000015145733677014000 5ustar www-datawww-datainline_svg-1.10.0/.gitignore0000644000004100000410000000024215145733677015766 0ustar www-datawww-data*.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp .ruby-* inline_svg-1.10.0/inline_svg.gemspec0000644000004100000410000000227515145733677017510 0ustar www-datawww-data# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'inline_svg/version' Gem::Specification.new do |spec| spec.name = "inline_svg" spec.version = InlineSvg::VERSION spec.authors = ["James Martin"] spec.email = ["inline_svg@jmrtn.com"] spec.summary = %q{Embeds an SVG document, inline.} spec.description = %q{Get an SVG into your view and then style it with CSS.} spec.homepage = "https://github.com/jamesmartin/inline_svg" spec.license = "MIT" spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.add_development_dependency "bundler", "~> 2.0" spec.add_development_dependency "rake" spec.add_development_dependency "rspec", "~> 3.2" spec.add_development_dependency "rspec_junit_formatter", "0.2.2" spec.add_development_dependency "pry" spec.add_development_dependency "rubocop" spec.add_runtime_dependency "activesupport", ">= 3.0" spec.add_runtime_dependency "nokogiri", ">= 1.6" end inline_svg-1.10.0/.github/0000755000004100000410000000000015145733677015340 5ustar www-datawww-datainline_svg-1.10.0/.github/workflows/0000755000004100000410000000000015145733677017375 5ustar www-datawww-datainline_svg-1.10.0/.github/workflows/ruby.yml0000644000004100000410000000054315145733677021103 0ustar www-datawww-dataname: Ruby on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Ruby 2.7 uses: ruby/setup-ruby@v1 with: ruby-version: 2.7.7 - name: Build and test with Rake run: | gem install bundler bundle install --jobs 4 --retry 3 bundle exec rake inline_svg-1.10.0/.github/workflows/rails_6_webpacker_integration_tests.yaml0000644000004100000410000000337715145733677027502 0ustar www-datawww-dataname: Rails 6 Webpacker Integration Tests (unreliable) on: [push] jobs: build: runs-on: ubuntu-latest strategy: matrix: test-branch: [rails6-webpacker] steps: - name: Checkout uses: actions/checkout@v2 - name: Checkout test app uses: actions/checkout@v2 with: repository: jamesmartin/inline_svg_test_app ref: ${{ matrix.test-branch }} path: test_app - name: Set up Ruby 3.1 uses: ruby/setup-ruby@v1 with: ruby-version: 3.1 - name: Build local gem run: | gem install bundler bundle install --jobs 4 --retry 3 bundle exec rake build - name: Use the local gem in the test App id: uselocalgem uses: jacobtomlinson/gha-find-replace@0.1.1 with: find: "gem 'inline_svg'" replace: "gem 'inline_svg', path: '${{github.workspace}}'" - name: Check local gem in use run: | test "${{ steps.uselocalgem.outputs.modifiedFiles }}" != "0" grep "inline_svg" $GITHUB_WORKSPACE/test_app/Gemfile - name: Bundle run: | cd $GITHUB_WORKSPACE/test_app bundle install --jobs 4 --retry 3 - name: Set up Node.js 16.x uses: actions/setup-node@v2 with: node-version: 16 if: matrix.test-branch == 'rails6-webpacker' - name: Set up Python 2.7 uses: actions/setup-python@v4 with: python-version: '2.7' - name: Generate Webpacker config run: | cd $GITHUB_WORKSPACE/test_app CXXFLAGS="--std=c++17" yarn install --check-files bundle exec rake webpacker:compile if: matrix.test-branch == 'rails6-webpacker' - name: Test run: | cd $GITHUB_WORKSPACE/test_app bundle exec rake test inline_svg-1.10.0/.github/workflows/integration_test.yml0000644000004100000410000000241015145733677023477 0ustar www-datawww-dataname: Integration Tests on: [push] jobs: build: runs-on: ubuntu-latest strategy: matrix: test-branch: [rails5, rails6, rails7] timeout-minutes: 20 steps: - name: Checkout uses: actions/checkout@v2 - name: Checkout test app uses: actions/checkout@v2 with: repository: jamesmartin/inline_svg_test_app ref: ${{ matrix.test-branch }} path: test_app - name: Set up Ruby 2.7 uses: ruby/setup-ruby@v1 with: ruby-version: 2.7.7 - name: Build local gem run: | gem install bundler bundle install --jobs 4 --retry 3 bundle exec rake build - name: Use the local gem in the test App id: uselocalgem uses: jacobtomlinson/gha-find-replace@0.1.1 with: find: "gem 'inline_svg'" replace: "gem 'inline_svg', path: '${{github.workspace}}'" - name: Check local gem in use run: | test "${{ steps.uselocalgem.outputs.modifiedFiles }}" != "0" grep "inline_svg" $GITHUB_WORKSPACE/test_app/Gemfile - name: Bundle run: | cd $GITHUB_WORKSPACE/test_app bundle install --jobs 4 --retry 3 - name: Test run: | cd $GITHUB_WORKSPACE/test_app bundle exec rake test inline_svg-1.10.0/lib/0000755000004100000410000000000015145733677014546 5ustar www-datawww-datainline_svg-1.10.0/lib/inline_svg/0000755000004100000410000000000015145733677016703 5ustar www-datawww-datainline_svg-1.10.0/lib/inline_svg/asset_file.rb0000644000004100000410000000052215145733677021345 0ustar www-datawww-datamodule InlineSvg class AssetFile class FileNotFound < IOError; end UNREADABLE_PATH = '' def self.named(filename) asset_path = FindsAssetPaths.by_filename(filename) File.read(asset_path || UNREADABLE_PATH) rescue Errno::ENOENT raise FileNotFound.new("Asset not found: #{asset_path}") end end end inline_svg-1.10.0/lib/inline_svg/cached_asset_file.rb0000644000004100000410000000527615145733677022647 0ustar www-datawww-data# frozen_string_literal: true module InlineSvg class CachedAssetFile attr_reader :assets, :filters, :paths # For each of the given paths, recursively reads each asset and stores its # contents alongside the full path to the asset. # # paths - One or more String representing directories on disk to search # for asset files. Note: paths are searched recursively. # filters - One or more Strings/Regexps to match assets against. Only # assets matching all filters will be cached and available to load. # Note: Specifying no filters will cache every file found in # paths. # def initialize(paths: [], filters: []) @paths = Array(paths).compact.map { |p| Pathname.new(p) } @filters = Array(filters).map { |f| Regexp.new(f) } @assets = @paths.reduce({}) { |assets, p| assets.merge(read_assets(assets, p)) } @sorted_asset_keys = assets.keys.sort { |a, b| a.size <=> b.size } end # Public: Finds the named asset and returns the contents as a string. # # asset_name - A string representing the name of the asset to load # # Returns: A String or raises InlineSvg::AssetFile::FileNotFound error def named(asset_name) assets[key_for_asset(asset_name)] or raise InlineSvg::AssetFile::FileNotFound.new("Asset not found: #{asset_name}") end private # Internal: Finds the key for a given asset name (using a Regex). In the # event of an ambiguous asset_name matching multiple assets, this method # ranks the matches by their full file path, choosing the shortest (most # exact) match over all others. # # Returns a String representing the key for the named asset or nil if there # is no match. def key_for_asset(asset_name) @sorted_asset_keys.find { |k| k.include?(asset_name) } end # Internal: Recursively descends through current_paths reading each file it # finds and adding them to the accumulator if the fullpath of the file # matches all configured filters. # # acc - Hash representing the accumulated assets keyed by full path # paths - Pathname representing the current node in the directory # structure to consider # # Returns a Hash containing the contents of each asset, keyed by fullpath # to the asset. def read_assets(acc, paths) paths.each_child do |child| if child.directory? read_assets(acc, child) elsif child.readable_real? acc[child.to_s] = File.read(child) if matches_all_filters?(child) end end acc end def matches_all_filters?(path) filters.all? { |f| f.match(path.to_s) } end end end inline_svg-1.10.0/lib/inline_svg/webpack_asset_finder.rb0000644000004100000410000000307415145733677023376 0ustar www-datawww-datamodule InlineSvg class WebpackAssetFinder def self.find_asset(filename) new(filename) end def initialize(filename) @filename = filename manifest_lookup = asset_helper.manifest.lookup(@filename) @asset_path = manifest_lookup.present? ? URI(manifest_lookup).path : "" end def pathname return if @asset_path.blank? if asset_helper.dev_server.running? dev_server_asset(@asset_path) elsif asset_helper.config.public_path.present? File.join(asset_helper.config.public_path, @asset_path) end end private def asset_helper @asset_helper ||= if defined?(::Shakapacker) ::Shakapacker else ::Webpacker end end def dev_server_asset(file_path) asset = fetch_from_dev_server(file_path) begin Tempfile.new(file_path).tap do |file| file.binmode file.write(asset) file.rewind end rescue StandardError => e Rails.logger.error "[inline_svg] Error creating tempfile for #{@filename}: #{e}" raise end end def fetch_from_dev_server(file_path) http = Net::HTTP.new(asset_helper.dev_server.host, asset_helper.dev_server.port) http.use_ssl = asset_helper.dev_server.protocol == "https" http.verify_mode = OpenSSL::SSL::VERIFY_NONE http.request(Net::HTTP::Get.new(file_path)).body rescue StandardError => e Rails.logger.error "[inline_svg] Error fetching #{@filename} from webpack-dev-server: #{e}" raise end end end inline_svg-1.10.0/lib/inline_svg/static_asset_finder.rb0000644000004100000410000000151515145733677023247 0ustar www-datawww-datarequire "pathname" # Naive fallback asset finder for when sprockets >= 3.0 && # config.assets.precompile = false # Thanks to @ryanswood for the original code: # https://github.com/jamesmartin/inline_svg/commit/661bbb3bef7d1b4bd6ccd63f5f018305797b9509 module InlineSvg class StaticAssetFinder def self.find_asset(filename) new(filename) end def initialize(filename) @filename = filename end def pathname if ::Rails.application.config.assets.compile asset = ::Rails.application.assets[@filename] Pathname.new(asset.filename) if asset.present? else manifest = ::Rails.application.assets_manifest asset_path = manifest.assets[@filename] unless asset_path.nil? ::Rails.root.join(manifest.directory, asset_path) end end end end end inline_svg-1.10.0/lib/inline_svg/id_generator.rb0000644000004100000410000000056715145733677021702 0ustar www-datawww-datarequire 'digest' module InlineSvg class IdGenerator class Randomness require "securerandom" def self.call SecureRandom.hex(10) end end def self.generate(base, salt, randomness: Randomness) bytes = Digest::SHA1.digest("#{base}-#{salt}-#{randomness.call}") 'a' + Digest.hexencode(bytes).to_i(16).to_s(36) end end end inline_svg-1.10.0/lib/inline_svg/action_view/0000755000004100000410000000000015145733677021212 5ustar www-datawww-datainline_svg-1.10.0/lib/inline_svg/action_view/helpers.rb0000644000004100000410000000536115145733677023206 0ustar www-datawww-datarequire 'action_view/helpers' if defined?(Rails) require 'action_view/context' if defined?(Rails) module InlineSvg module ActionView module Helpers def inline_svg_tag(filename, transform_params={}) with_asset_finder(InlineSvg.configuration.asset_finder) do render_inline_svg(filename, transform_params) end end def inline_svg_pack_tag(filename, transform_params={}) with_asset_finder(InlineSvg::WebpackAssetFinder) do render_inline_svg(filename, transform_params) end end def inline_svg(filename, transform_params={}) render_inline_svg(filename, transform_params) end private def backwards_compatible_html_escape(filename) # html_escape_once was introduced in newer versions of Rails. if ERB::Util.respond_to?(:html_escape_once) ERB::Util.html_escape_once(filename) else ERB::Util.html_escape(filename) end end def render_inline_svg(filename, transform_params={}) begin svg_file = read_svg(filename) rescue InlineSvg::AssetFile::FileNotFound => error raise error if InlineSvg.configuration.raise_on_file_not_found? return placeholder(filename) unless transform_params[:fallback].present? if transform_params[:fallback].present? begin svg_file = read_svg(transform_params[:fallback]) rescue InlineSvg::AssetFile::FileNotFound placeholder(filename) end end end InlineSvg::TransformPipeline.generate_html_from(svg_file, transform_params).html_safe end def read_svg(filename) if InlineSvg::IOResource === filename InlineSvg::IOResource.read filename else configured_asset_file.named filename end end def placeholder(filename) css_class = InlineSvg.configuration.svg_not_found_css_class not_found_message = "'#{backwards_compatible_html_escape(filename)}' #{extension_hint(filename)}" if css_class.nil? return "".html_safe else return "".html_safe end end def configured_asset_file InlineSvg.configuration.asset_file end def with_asset_finder(asset_finder) Thread.current[:inline_svg_asset_finder] = asset_finder output = yield Thread.current[:inline_svg_asset_finder] = nil output end def extension_hint(filename) filename.ends_with?(".svg") ? "" : "(Try adding .svg to your filename) " end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/0000755000004100000410000000000015145733677022603 5ustar www-datawww-datainline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/0000755000004100000410000000000015145733677026034 5ustar www-datawww-datainline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/transformation.rb0000644000004100000410000000217415145733677031433 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class Transformation def self.create_with_value(value) self.new(value) end attr_reader :value def initialize(value) @value = value end def transform(*) raise "#transform should be implemented by subclasses of Transformation" end # Parses a document and yields the contained SVG nodeset to the given block # if it exists. # # Returns a Nokogiri::XML::Document. def with_svg(doc) doc = Nokogiri::XML::Document.parse( doc.to_html(encoding: "UTF-8"), nil, "UTF-8" ) svg = doc.at_css "svg" yield svg if svg && block_given? doc end end class NullTransformation < Transformation def transform(doc) doc end end end module InlineSvg class CustomTransformation < InlineSvg::TransformPipeline::Transformations::Transformation # Inherit from this class to keep custom transformation class definitions short # E.g. # class MyTransform < InlineSvg::CustomTransformation # def transform(doc) # # Your code here... # end # end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/preserve_aspect_ratio.rb0000644000004100000410000000034215145733677032750 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class PreserveAspectRatio < Transformation def transform(doc) with_svg(doc) do |svg| svg["preserveAspectRatio"] = self.value end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/style_attribute.rb0000644000004100000410000000043315145733677031604 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class StyleAttribute < Transformation def transform(doc) with_svg(doc) do |svg| styles = svg["style"].to_s.split(";") styles << value svg["style"] = styles.join(";") end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/title.rb0000644000004100000410000000051715145733677027505 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class Title < Transformation def transform(doc) with_svg(doc) do |svg| node = Nokogiri::XML::Node.new("title", doc) node.content = value svg.search("title").each { |node| node.remove } svg.prepend_child(node) end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/data_attributes.rb0000644000004100000410000000071415145733677031542 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class DataAttributes < Transformation def transform(doc) with_svg(doc) do |svg| with_valid_hash_from(self.value).each_pair do |name, data| svg["data-#{dasherize(name)}"] = data end end end private def with_valid_hash_from(hash) Hash.try_convert(hash) || {} end def dasherize(string) string.to_s.gsub(/_/, "-") end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/description.rb0000644000004100000410000000052315145733677030704 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class Description < Transformation def transform(doc) with_svg(doc) do |svg| node = Nokogiri::XML::Node.new("desc", doc) node.content = value svg.search("desc").each { |node| node.remove } svg.prepend_child(node) end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/aria_attributes.rb0000644000004100000410000000156115145733677031546 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class AriaAttributes < Transformation def transform(doc) with_svg(doc) do |svg| # Add role svg["role"] = "img" # Build aria-labelledby string aria_elements = [] svg.search("title").each do |element| aria_elements << element["id"] = element_id_for("title", element) end svg.search("desc").each do |element| aria_elements << element["id"] = element_id_for("desc", element) end if aria_elements.any? svg["aria-labelledby"] = aria_elements.join(" ") end end end def element_id_for(base, element) if element["id"].nil? InlineSvg::IdGenerator.generate(base, element.text) else InlineSvg::IdGenerator.generate(element["id"], element.text) end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/id_attribute.rb0000644000004100000410000000031115145733677031033 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class IdAttribute < Transformation def transform(doc) with_svg(doc) do |svg| svg["id"] = self.value end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/height.rb0000644000004100000410000000031015145733677027623 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class Height < Transformation def transform(doc) with_svg(doc) do |svg| svg["height"] = self.value end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/size.rb0000644000004100000410000000064315145733677027336 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class Size < Transformation def transform(doc) with_svg(doc) do |svg| svg["width"] = width_of(self.value) svg["height"] = height_of(self.value) end end def width_of(value) value.split(/\*/).map(&:strip)[0] end def height_of(value) value.split(/\*/).map(&:strip)[1] || width_of(value) end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/aria_hidden.rb0000644000004100000410000000032115145733677030604 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class AriaHidden < Transformation def transform(doc) with_svg(doc) do |svg| svg["aria-hidden"] = self.value end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/aria_hidden_attribute.rb0000644000004100000410000000033215145733677032671 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class AriaHiddenAttribute < Transformation def transform(doc) with_svg(doc) do |svg| svg["aria-hidden"] = self.value end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/no_comment.rb0000644000004100000410000000044015145733677030515 0ustar www-datawww-datamodule InlineSvg::TransformPipeline module Transformations class NoComment < Transformation def transform(doc) with_svg(doc) do |svg| svg.xpath("//comment()").each do |comment| comment.remove end end end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/width.rb0000644000004100000410000000030615145733677027477 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class Width < Transformation def transform(doc) with_svg(doc) do |svg| svg["width"] = self.value end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/view_box.rb0000644000004100000410000000030515145733677030201 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class ViewBox < Transformation def transform(doc) with_svg(doc) do |svg| svg["viewBox"] = value end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations/class_attribute.rb0000644000004100000410000000044115145733677031550 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations class ClassAttribute < Transformation def transform(doc) with_svg(doc) do |svg| classes = (svg["class"] || "").split(" ") classes << value svg["class"] = classes.join(" ") end end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline/transformations.rb0000644000004100000410000000667715145733677026401 0ustar www-datawww-datamodule InlineSvg::TransformPipeline::Transformations # Transformations are run in priority order, lowest number first: def self.built_in_transformations { id: { transform: IdAttribute, priority: 1 }, desc: { transform: Description, priority: 2 }, title: { transform: Title, priority: 3 }, aria: { transform: AriaAttributes }, aria_hidden: { transform: AriaHiddenAttribute }, class: { transform: ClassAttribute }, style: { transform: StyleAttribute }, data: { transform: DataAttributes }, nocomment: { transform: NoComment }, preserve_aspect_ratio: { transform: PreserveAspectRatio }, size: { transform: Size }, width: { transform: Width }, height: { transform: Height }, view_box: { transform: ViewBox }, } end def self.custom_transformations magnify_priorities(InlineSvg.configuration.custom_transformations) end def self.magnify_priorities(transforms) transforms.inject({}) do |output, (name, definition)| priority = definition.fetch(:priority, built_in_transformations.size) output[name] = definition.merge( { priority: magnify(priority) } ) output end end def self.magnify(priority=0) (priority + 1) * built_in_transformations.size end def self.all_transformations in_priority_order(built_in_transformations.merge(custom_transformations)) end def self.lookup(transform_params) return [] unless transform_params.any? || custom_transformations.any? transform_params_with_defaults = params_with_defaults(transform_params) all_transformations.map { |name, definition| value = transform_params_with_defaults[name] definition.fetch(:transform, no_transform).create_with_value(value) if value }.compact end def self.in_priority_order(transforms) transforms.sort_by { |_, options| options.fetch(:priority, transforms.size) } end def self.params_with_defaults(params) without_empty_values(all_default_values.merge(params)) end def self.without_empty_values(params) params.reject {|key, value| value.nil?} end def self.all_default_values custom_transformations .values .select {|opt| opt[:default_value] != nil} .map {|opt| [opt[:attribute], opt[:default_value]]} .inject({}) {|options, attrs| options.merge!(attrs[0] => attrs[1])} end def self.no_transform InlineSvg::TransformPipeline::Transformations::NullTransformation end end require 'inline_svg/transform_pipeline/transformations/transformation' require 'inline_svg/transform_pipeline/transformations/no_comment' require 'inline_svg/transform_pipeline/transformations/class_attribute' require 'inline_svg/transform_pipeline/transformations/style_attribute' require 'inline_svg/transform_pipeline/transformations/title' require 'inline_svg/transform_pipeline/transformations/description' require 'inline_svg/transform_pipeline/transformations/size' require 'inline_svg/transform_pipeline/transformations/height' require 'inline_svg/transform_pipeline/transformations/width' require 'inline_svg/transform_pipeline/transformations/view_box' require 'inline_svg/transform_pipeline/transformations/id_attribute' require 'inline_svg/transform_pipeline/transformations/data_attributes' require 'inline_svg/transform_pipeline/transformations/preserve_aspect_ratio' require 'inline_svg/transform_pipeline/transformations/aria_attributes' require "inline_svg/transform_pipeline/transformations/aria_hidden_attribute" inline_svg-1.10.0/lib/inline_svg/finds_asset_paths.rb0000644000004100000410000000052115145733677022727 0ustar www-datawww-datamodule InlineSvg class FindsAssetPaths def self.by_filename(filename) asset = configured_asset_finder.find_asset(filename) asset.try(:pathname) || asset.try(:filename) end def self.configured_asset_finder Thread.current[:inline_svg_asset_finder] || InlineSvg.configuration.asset_finder end end end inline_svg-1.10.0/lib/inline_svg/io_resource.rb0000644000004100000410000000055615145733677021554 0ustar www-datawww-datamodule InlineSvg module IOResource def self.===(object) object.is_a?(IO) || object.is_a?(StringIO) end def self.default_for(object) case object when StringIO then '' when IO then 1 end end def self.read(object) start = object.pos str = object.read object.seek start str end end end inline_svg-1.10.0/lib/inline_svg/transform_pipeline.rb0000644000004100000410000000066215145733677023134 0ustar www-datawww-datamodule InlineSvg module TransformPipeline def self.generate_html_from(svg_file, transform_params) document = Nokogiri::XML::Document.parse(svg_file) Transformations.lookup(transform_params).reduce(document) do |doc, transformer| transformer.transform(doc) end.to_html.strip end end end require 'nokogiri' require 'inline_svg/id_generator' require 'inline_svg/transform_pipeline/transformations' inline_svg-1.10.0/lib/inline_svg/version.rb0000644000004100000410000000005215145733677020712 0ustar www-datawww-datamodule InlineSvg VERSION = "1.10.0" end inline_svg-1.10.0/lib/inline_svg/railtie.rb0000644000004100000410000000136515145733677020666 0ustar www-datawww-datarequire 'rails/railtie' module InlineSvg class Railtie < ::Rails::Railtie initializer "inline_svg.action_view" do |app| ActiveSupport.on_load :action_view do require "inline_svg/action_view/helpers" include InlineSvg::ActionView::Helpers end end config.after_initialize do |app| InlineSvg.configure do |config| # Configure the asset_finder: # Only set this when a user-configured asset finder has not been # configured already. if config.asset_finder.nil? # In default Rails apps, this will be a fully operational # Sprockets::Environment instance config.asset_finder = app.instance_variable_get(:@assets) end end end end end inline_svg-1.10.0/lib/inline_svg/propshaft_asset_finder.rb0000644000004100000410000000050615145733677023765 0ustar www-datawww-datamodule InlineSvg class PropshaftAssetFinder def self.find_asset(filename) new(filename) end def initialize(filename) @filename = filename end def pathname asset_path = ::Rails.application.assets.load_path.find(@filename) asset_path.path unless asset_path.nil? end end end inline_svg-1.10.0/lib/inline_svg.rb0000644000004100000410000000627715145733677017244 0ustar www-datawww-datarequire "inline_svg/version" require "inline_svg/action_view/helpers" require "inline_svg/asset_file" require "inline_svg/cached_asset_file" require "inline_svg/finds_asset_paths" require "inline_svg/propshaft_asset_finder" require "inline_svg/static_asset_finder" require "inline_svg/webpack_asset_finder" require "inline_svg/transform_pipeline" require "inline_svg/io_resource" require "inline_svg/railtie" if defined?(Rails) require 'active_support' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string' require 'nokogiri' module InlineSvg class Configuration class Invalid < ArgumentError; end attr_reader :asset_file, :asset_finder, :custom_transformations, :svg_not_found_css_class def initialize @custom_transformations = {} @asset_file = InlineSvg::AssetFile @svg_not_found_css_class = nil @raise_on_file_not_found = false end def asset_file=(custom_asset_file) begin method = custom_asset_file.method(:named) if method.arity == 1 @asset_file = custom_asset_file else raise InlineSvg::Configuration::Invalid.new("asset_file should implement the #named method with arity 1") end rescue NameError raise InlineSvg::Configuration::Invalid.new("asset_file should implement the #named method") end end def asset_finder=(finder) @asset_finder = if finder.respond_to?(:find_asset) finder elsif finder.class.name == "Propshaft::Assembly" InlineSvg::PropshaftAssetFinder else # fallback to a naive static asset finder # (sprokects >= 3.0 && config.assets.precompile = false # See: https://github.com/jamesmartin/inline_svg/issues/25 InlineSvg::StaticAssetFinder end asset_finder end def svg_not_found_css_class=(css_class) if css_class.present? && css_class.is_a?(String) @svg_not_found_css_class = css_class end end def add_custom_transformation(options) if incompatible_transformation?(options.fetch(:transform)) raise InlineSvg::Configuration::Invalid.new("#{options.fetch(:transform)} should implement the .create_with_value and #transform methods") end @custom_transformations.merge!(Hash[ *[options.fetch(:attribute, :no_attribute), options] ]) end def raise_on_file_not_found=(value) @raise_on_file_not_found = value end def raise_on_file_not_found? !!@raise_on_file_not_found end private def incompatible_transformation?(klass) !klass.is_a?(Class) || !klass.respond_to?(:create_with_value) || !klass.instance_methods.include?(:transform) end end @configuration = InlineSvg::Configuration.new class << self attr_reader :configuration def configure if block_given? yield configuration else raise InlineSvg::Configuration::Invalid.new('Please set configuration options with a block') end end def reset_configuration! @configuration = InlineSvg::Configuration.new end end end inline_svg-1.10.0/LICENSE.txt0000644000004100000410000000205515145733677015625 0ustar www-datawww-dataCopyright (c) 2014 James Martin MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. inline_svg-1.10.0/spec/0000755000004100000410000000000015145733677014732 5ustar www-datawww-datainline_svg-1.10.0/spec/propshaft_asset_finder_spec.rb0000644000004100000410000000165115145733677023030 0ustar www-datawww-datarequire_relative '../lib/inline_svg' describe InlineSvg::PropshaftAssetFinder do context "when the file is not found" do it "returns nil" do stub_const('Rails', double('Rails').as_null_object) expect(::Rails.application.assets.load_path).to receive(:find).with('some-file').and_return(nil) expect(InlineSvg::PropshaftAssetFinder.find_asset('some-file').pathname).to be_nil end end context "when the file is found" do it "returns fully qualified file paths from Propshaft" do stub_const('Rails', double('Rails').as_null_object) asset = double('Asset') expect(asset).to receive(:path).and_return(Pathname.new('/full/path/to/some-file')) expect(::Rails.application.assets.load_path).to receive(:find).with('some-file').and_return(asset) expect(InlineSvg::PropshaftAssetFinder.find_asset('some-file').pathname).to eq Pathname('/full/path/to/some-file') end end end inline_svg-1.10.0/spec/inline_svg_spec.rb0000644000004100000410000001065615145733677020436 0ustar www-datawww-datarequire_relative '../lib/inline_svg' class MyCustomTransform def self.create_with_value(value); end def transform(doc); end end class MyInvalidCustomTransformKlass def transform(doc); end end class MyInvalidCustomTransformInstance def self.create_with_value(value); end end class MyCustomAssetFile def self.named(filename); end end describe InlineSvg do describe "configuration" do context "when a block is not given" do it "complains" do expect do InlineSvg.configure end.to raise_error(InlineSvg::Configuration::Invalid) end end context "asset finder" do it "allows an asset finder to be assigned" do sprockets = double('SomethingLikeSprockets', find_asset: 'some asset') InlineSvg.configure do |config| config.asset_finder = sprockets end expect(InlineSvg.configuration.asset_finder).to eq sprockets end it "falls back to StaticAssetFinder when the provided asset finder does not implement #find_asset" do InlineSvg.configure do |config| config.asset_finder = 'Not a real asset finder' end expect(InlineSvg.configuration.asset_finder).to eq InlineSvg::StaticAssetFinder end end context "configuring a custom asset file" do it "falls back to the built-in asset file implementation by default" do expect(InlineSvg.configuration.asset_file).to eq(InlineSvg::AssetFile) end it "adds a collaborator that meets the interface specification" do InlineSvg.configure do |config| config.asset_file = MyCustomAssetFile end expect(InlineSvg.configuration.asset_file).to eq MyCustomAssetFile end it "rejects a collaborator that does not conform to the interface spec" do bad_asset_file = double("bad_asset_file") expect do InlineSvg.configure do |config| config.asset_file = bad_asset_file end end.to raise_error(InlineSvg::Configuration::Invalid, /asset_file should implement the #named method/) end it "rejects a collaborator that implements the correct interface with the wrong arity" do bad_asset_file = double("bad_asset_file", named: nil) expect do InlineSvg.configure do |config| config.asset_file = bad_asset_file end end.to raise_error(InlineSvg::Configuration::Invalid, /asset_file should implement the #named method with arity 1/) end end context "configuring the default svg-not-found class" do it "sets the class name" do InlineSvg.configure do |config| config.svg_not_found_css_class = 'missing-svg' end expect(InlineSvg.configuration.svg_not_found_css_class).to eq 'missing-svg' end end context "configuring custom transformation" do it "allows a custom transformation to be added" do InlineSvg.configure do |config| config.add_custom_transformation(attribute: :my_transform, transform: MyCustomTransform) end expect(InlineSvg.configuration.custom_transformations).to eq({my_transform: {attribute: :my_transform, transform: MyCustomTransform}}) end it "rejects transformations that do not implement .create_with_value" do expect do InlineSvg.configure do |config| config.add_custom_transformation(attribute: :irrelevant, transform: MyInvalidCustomTransformKlass) end end.to raise_error(InlineSvg::Configuration::Invalid, /#{MyInvalidCustomTransformKlass} should implement the .create_with_value and #transform methods/) end it "rejects transformations that does not implement #transform" do expect do InlineSvg.configure do |config| config.add_custom_transformation(attribute: :irrelevant, transform: MyInvalidCustomTransformInstance) end end.to raise_error(InlineSvg::Configuration::Invalid, /#{MyInvalidCustomTransformInstance} should implement the .create_with_value and #transform methods/) end it "rejects transformations that are not classes" do expect do InlineSvg.configure do |config| config.add_custom_transformation(attribute: :irrelevant, transform: :not_a_class) end end.to raise_error(InlineSvg::Configuration::Invalid, /#{:not_a_class} should implement the .create_with_value and #transform methods/) end end end end inline_svg-1.10.0/spec/webpack_asset_finder_spec.rb0000644000004100000410000000150415145733677022433 0ustar www-datawww-datarequire_relative '../lib/inline_svg' describe InlineSvg::WebpackAssetFinder do context "when the file is not found" do it "returns nil" do stub_const('Rails', double('Rails').as_null_object) stub_const('Webpacker', double('Webpacker').as_null_object) expect(::Webpacker.manifest).to receive(:lookup).with('some-file').and_return(nil) expect(described_class.find_asset('some-file').pathname).to be_nil end end context "when Shakapacker is defined" do it "uses the new spelling" do stub_const('Rails', double('Rails').as_null_object) stub_const('Shakapacker', double('Shakapacker').as_null_object) expect(::Shakapacker.manifest).to receive(:lookup).with('some-file').and_return(nil) expect(described_class.find_asset('some-file').pathname).to be_nil end end end inline_svg-1.10.0/spec/cached_asset_file_spec.rb0000644000004100000410000000564315145733677021706 0ustar www-datawww-data# frozen_string_literal: true require 'pathname' require_relative '../lib/inline_svg' describe InlineSvg::CachedAssetFile do let(:fixture_path) { Pathname.new(File.expand_path("../files/static_assets", __FILE__)) } it "loads assets under configured paths" do known_document = File.read(fixture_path.join("assets0", "known-document.svg")) asset_loader = InlineSvg::CachedAssetFile.new(paths: fixture_path.join("assets0")) expect(asset_loader.named("known-document.svg")).to eq(known_document) end it "does not include assets outside of configured paths" do asset_loader = InlineSvg::CachedAssetFile.new(paths: fixture_path.join("assets0")) expect(fixture_path.join("assets1", "other-document.svg")).to be_file expect do asset_loader.named("other-document.svg") end.to raise_error InlineSvg::AssetFile::FileNotFound end it "differentiates two files with the same name" do known_document_0 = File.read(fixture_path.join("assets0", "known-document.svg")) known_document_1 = File.read(fixture_path.join("assets1", "known-document.svg")) expect(known_document_0).not_to eq(known_document_1) asset_loader = InlineSvg::CachedAssetFile.new(paths: fixture_path) expect(known_document_0).to eq(asset_loader.named("assets0/known-document.svg")) expect(known_document_1).to eq(asset_loader.named("assets1/known-document.svg")) end it "chooses the closest exact matching file when similar files exist in the same path" do known_document = File.read(fixture_path.join("assets0", "known-document.svg")) known_document_2 = File.read(fixture_path.join("assets0", "known-document-two.svg")) expect(known_document).not_to eq(known_document_2) asset_loader = InlineSvg::CachedAssetFile.new(paths: fixture_path.join("assets0"), filters: /\.svg/) expect(asset_loader.named("known-document")).to eq(known_document) expect(asset_loader.named("known-document-two")).to eq(known_document_2) end it "filters wanted files by simple string matching" do known_document_0 = File.read(fixture_path.join("assets0", "known-document.svg")) known_document_1 = File.read(fixture_path.join("assets1", "known-document.svg")) asset_loader = InlineSvg::CachedAssetFile.new(paths: fixture_path, filters: "assets1") expect do asset_loader.named("assets0/known-document.svg") end.to raise_error InlineSvg::AssetFile::FileNotFound expect(known_document_1).to eq(asset_loader.named("assets1/known-document.svg")) end it "filters wanted files by regex matching" do known_document_1 = File.read(fixture_path.join("assets1", "known-document.svg")) asset_loader = InlineSvg::CachedAssetFile.new(paths: fixture_path, filters: ["assets1", /\.svg/]) expect do asset_loader.named("assets1/some-file.txt") end.to raise_error InlineSvg::AssetFile::FileNotFound expect(known_document_1).to eq(asset_loader.named("assets1/known-document.svg")) end end inline_svg-1.10.0/spec/files/0000755000004100000410000000000015145733677016034 5ustar www-datawww-datainline_svg-1.10.0/spec/files/example.svg0000644000004100000410000000017215145733677020210 0ustar www-datawww-data inline_svg-1.10.0/spec/files/static_assets/0000755000004100000410000000000015145733677020705 5ustar www-datawww-datainline_svg-1.10.0/spec/files/static_assets/assets1/0000755000004100000410000000000015145733677022270 5ustar www-datawww-datainline_svg-1.10.0/spec/files/static_assets/assets1/known-document.svg0000644000004100000410000000004215145733677025755 0ustar www-datawww-dataAnother known document inline_svg-1.10.0/spec/files/static_assets/assets1/other-document.svg0000644000004100000410000000024415145733677025746 0ustar www-datawww-data Other document inline_svg-1.10.0/spec/files/static_assets/assets1/some-file.txt0000644000004100000410000000002415145733677024705 0ustar www-datawww-dataSome file contents. inline_svg-1.10.0/spec/files/static_assets/assets0/0000755000004100000410000000000015145733677022267 5ustar www-datawww-datainline_svg-1.10.0/spec/files/static_assets/assets0/known-document.svg0000644000004100000410000000003715145733677025760 0ustar www-datawww-datainteresting content inline_svg-1.10.0/spec/files/static_assets/assets0/known-document-two.svg0000644000004100000410000000004515145733677026566 0ustar www-datawww-dataother interesting content inline_svg-1.10.0/spec/files/static_assets/assets0/some-document.svg0000644000004100000410000000146315145733677025573 0ustar www-datawww-data inline_svg-1.10.0/spec/id_generator_spec.rb0000644000004100000410000000054315145733677020735 0ustar www-datawww-datarequire_relative '../lib/inline_svg/id_generator' describe InlineSvg::IdGenerator do it "generates a hexencoded ID based on a salt and a random value" do randomizer = -> { "some-random-value" } expect(InlineSvg::IdGenerator.generate("some-base", "some-salt", randomness: randomizer)). to eq("at2c17mkqnvopy36iccxspura7wnreqf") end end inline_svg-1.10.0/spec/finds_asset_paths_spec.rb0000644000004100000410000000627215145733677022001 0ustar www-datawww-datarequire 'pathname' require_relative '../lib/inline_svg' describe InlineSvg::FindsAssetPaths do context "when sprockets finder returns an object which supports only the pathname method" do it "returns fully qualified file paths from Sprockets" do sprockets = double('SprocketsDouble') expect(sprockets).to receive(:find_asset).with('some-file'). and_return(double(pathname: Pathname('/full/path/to/some-file'))) InlineSvg.configure do |config| config.asset_finder = sprockets end expect(InlineSvg::FindsAssetPaths.by_filename('some-file')).to eq Pathname('/full/path/to/some-file') end end context "when sprockets finder returns an object which supports only the filename method" do it "returns fully qualified file paths from Sprockets" do sprockets = double('SprocketsDouble') expect(sprockets).to receive(:find_asset).with('some-file'). and_return(double(filename: Pathname('/full/path/to/some-file'))) InlineSvg.configure do |config| config.asset_finder = sprockets end expect(InlineSvg::FindsAssetPaths.by_filename('some-file')).to eq Pathname('/full/path/to/some-file') end end context "when asset is not found" do it "returns nil" do sprockets = double('SprocketsDouble') expect(sprockets).to receive(:find_asset).with('some-file').and_return(nil) InlineSvg.configure do |config| config.asset_finder = sprockets end expect(InlineSvg::FindsAssetPaths.by_filename('some-file')).to be_nil end end context "when propshaft finder returns an object which supports only the pathname method" do it "returns fully qualified file paths from Propshaft" do propshaft = double('PropshaftDouble') expect(propshaft).to receive(:find_asset).with('some-file'). and_return(double(pathname: Pathname('/full/path/to/some-file'))) InlineSvg.configure do |config| config.asset_finder = propshaft end expect(InlineSvg::FindsAssetPaths.by_filename('some-file')).to eq Pathname('/full/path/to/some-file') end end context "when webpack finder returns an object with a relative asset path" do it "returns the fully qualified file path" do webpacker = double('WebpackerDouble') expect(webpacker).to receive(:find_asset).with('some-file'). and_return(double(filename: Pathname('/full/path/to/some-file'))) InlineSvg.configure do |config| config.asset_finder = webpacker end expect(InlineSvg::FindsAssetPaths.by_filename('some-file')).to eq Pathname('/full/path/to/some-file') end end context "when webpack finder returns an object with an absolute http asset path" do it "returns the fully qualified file path" do webpacker = double('WebpackerDouble') expect(webpacker).to receive(:find_asset).with('some-file'). and_return(double(filename: Pathname('https://my-fancy-domain.test/full/path/to/some-file'))) InlineSvg.configure do |config| config.asset_finder = webpacker end expect(InlineSvg::FindsAssetPaths.by_filename('some-file')).to eq Pathname('https://my-fancy-domain.test/full/path/to/some-file') end end end inline_svg-1.10.0/spec/helpers/0000755000004100000410000000000015145733677016374 5ustar www-datawww-datainline_svg-1.10.0/spec/helpers/inline_svg_spec.rb0000644000004100000410000002564315145733677022102 0ustar www-datawww-datarequire 'inline_svg' class WorkingCustomTransform < InlineSvg::CustomTransformation def transform(doc) doc = Nokogiri::XML::Document.parse(doc.to_html) svg = doc.at_css 'svg' svg['custom'] = value doc end end describe InlineSvg::ActionView::Helpers do let(:helper) { ( Class.new { include InlineSvg::ActionView::Helpers } ).new } shared_examples "inline_svg helper" do |helper_method:| context "when passed the name of an SVG that does not exist" do after(:each) do InlineSvg.reset_configuration! end context "and configured to raise" do it "raises an exception" do InlineSvg.configure do |config| config.raise_on_file_not_found = true end allow(InlineSvg::AssetFile).to receive(:named). with('some-missing-file.svg'). and_raise(InlineSvg::AssetFile::FileNotFound.new) expect { helper.send(helper_method, 'some-missing-file.svg') }.to raise_error(InlineSvg::AssetFile::FileNotFound) end end it "returns an empty, html safe, SVG document as a placeholder" do allow(InlineSvg::AssetFile).to receive(:named). with('some-missing-file.svg'). and_raise(InlineSvg::AssetFile::FileNotFound.new) output = helper.send(helper_method, 'some-missing-file.svg') expect(output).to eq "" expect(output).to be_html_safe end it "escapes malicious input" do malicious = "-->.svg" allow(InlineSvg::AssetFile).to receive(:named). with(malicious). and_raise(InlineSvg::AssetFile::FileNotFound.new) output = helper.send(helper_method, malicious) expect(output).to eq "" expect(output).to be_html_safe end it "gives a helpful hint when no .svg extension is provided in the filename" do allow(InlineSvg::AssetFile).to receive(:named). with('missing-file-with-no-extension'). and_raise(InlineSvg::AssetFile::FileNotFound.new) output = helper.send(helper_method, 'missing-file-with-no-extension') expect(output).to eq "" end it "allows the CSS class on the empty SVG document to be changed" do InlineSvg.configure do |config| config.svg_not_found_css_class = 'missing-svg' end allow(InlineSvg::AssetFile).to receive(:named). with('some-other-missing-file.svg'). and_raise(InlineSvg::AssetFile::FileNotFound.new) output = helper.send(helper_method, 'some-other-missing-file.svg') expect(output).to eq "" expect(output).to be_html_safe end context "and a fallback that does exist" do it "displays the fallback" do allow(InlineSvg::AssetFile).to receive(:named). with('missing.svg'). and_raise(InlineSvg::AssetFile::FileNotFound.new) fallback_file = '' allow(InlineSvg::AssetFile).to receive(:named).with('fallback.svg').and_return(fallback_file) expect(helper.send(helper_method, 'missing.svg', fallback: 'fallback.svg')).to eq fallback_file end end end context "when passed an existing SVG file" do context "and no options" do it "returns a html safe version of the file's contents" do example_file = '' allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(example_file) expect(helper.send(helper_method, 'some-file')).to eq example_file end end context "and the 'title' option" do it "adds the title node to the SVG output" do input_svg = '' expected_output = 'A title' allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg) expect(helper.send(helper_method, 'some-file', title: 'A title')).to eq expected_output end end context "and the 'desc' option" do it "adds the description node to the SVG output" do input_svg = '' expected_output = 'A description' allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg) expect(helper.send(helper_method, 'some-file', desc: 'A description')).to eq expected_output end end context "and the 'nocomment' option" do it "strips comments and other unknown/unsafe nodes from the output" do input_svg = '' expected_output = '' allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg) expect(helper.send(helper_method, 'some-file', nocomment: true)).to eq expected_output end end context "and the 'aria_hidden' option" do it "sets 'aria-hidden=true' in the output" do input_svg = '' expected_output = '' allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg) expect(helper.send(helper_method, 'some-file', aria_hidden: true)).to eq expected_output end end context "and all options" do it "applies all expected transformations to the output" do input_svg = '' expected_output = 'A titleA description' allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg) expect(helper.send(helper_method, 'some-file', title: 'A title', desc: 'A description', nocomment: true)).to eq expected_output end end context "with custom transformations" do before(:each) do InlineSvg.configure do |config| config.add_custom_transformation({attribute: :custom, transform: WorkingCustomTransform}) end end after(:each) do InlineSvg.reset_configuration! end it "applies custm transformations to the output" do input_svg = '' expected_output = '' allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg) expect(helper.send(helper_method, 'some-file', custom: 'some value')).to eq expected_output end end context "with custom transformations using a default value" do before(:each) do InlineSvg.configure do |config| config.add_custom_transformation({attribute: :custom, transform: WorkingCustomTransform, default_value: 'default value'}) end end after(:each) do InlineSvg.reset_configuration! end context "without passing the attribute value" do it "applies custom transformations to the output using the default value" do input_svg = '' allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg) expect(helper.send(helper_method, 'some-file')).to eq "" end end context "passing the attribute value" do it "applies custom transformations to the output" do input_svg = '' allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg) expect(helper.send(helper_method, 'some-file', custom: 'some value')).to eq "" end end end end context 'argument polimorphizm' do let(:argument) { double('argument') } it 'accept IO' do expect(InlineSvg::IOResource).to receive(:===).with(argument).and_return(true) expect(InlineSvg::IOResource).to receive(:read).with(argument) expect(InlineSvg::AssetFile).to_not receive(:named) helper.send(helper_method, argument) end it 'accept filename' do expect(InlineSvg::IOResource).to receive(:===).with(argument).and_return(false) expect(InlineSvg::IOResource).to_not receive(:read) expect(InlineSvg::AssetFile).to receive(:named).with(argument) helper.send(helper_method, argument) end end context 'when passed IO object argument' do let(:io_object) { double('io_object') } let(:file_path) { File.expand_path('../../files/example.svg', __FILE__) } let(:answer) { File.read(file_path) } it 'return valid svg' do expect(InlineSvg::IOResource).to receive(:===).with(io_object).and_return(true) expect(InlineSvg::IOResource).to receive(:read).with(io_object).and_return("") output = helper.send(helper_method, io_object) expect(output).to eq "" expect(output).to be_html_safe end it 'return valid svg for file' do output = helper.send(helper_method, File.new(file_path)) expect(output).to eq "" expect(output).to be_html_safe end end context 'default output' do it "returns an SVG tag without any pre or post whitespace characters" do input_svg = '' allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg) expect(helper.send(helper_method, 'some-file')).to eq "" end end end describe '#inline_svg' do it_behaves_like "inline_svg helper", helper_method: :inline_svg end describe '#inline_svg_tag' do it_behaves_like "inline_svg helper", helper_method: :inline_svg_tag end describe '#inline_svg_tag' do it_behaves_like "inline_svg helper", helper_method: :inline_svg_pack_tag end end ���������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/asset_file_spec.rb�����������������������������������������������������������0000644�0000041�0000041�00000002011�15145733677�020401� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require_relative '../lib/inline_svg/finds_asset_paths' require_relative '../lib/inline_svg/asset_file' describe InlineSvg::AssetFile do it "reads data from a file, after qualifying a full path" do example_svg_path = File.expand_path(__FILE__, 'files/example.svg') expect(InlineSvg::FindsAssetPaths).to receive(:by_filename).with('some filename').and_return example_svg_path expect(InlineSvg::AssetFile.named('some filename')).to include('This is a test') end it "complains when the file cannot be read" do allow(InlineSvg::FindsAssetPaths).to receive(:by_filename).and_return('/this/path/does/not/exist') expect do InlineSvg::AssetFile.named('some missing file') end.to raise_error InlineSvg::AssetFile::FileNotFound end it "complains when the file path was not found" do allow(InlineSvg::FindsAssetPaths).to receive(:by_filename).and_return(nil) expect do InlineSvg::AssetFile.named('some missing file') end.to raise_error InlineSvg::AssetFile::FileNotFound end end �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/�����������������������������������������������������0000755�0000041�0000041�00000000000�15145733677�021665� 5����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/�������������������������������������0000755�0000041�0000041�00000000000�15145733677�025116� 5����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/data_attributes_spec.rb��������������0000644�0000041�0000041�00000004233�15145733677�031636� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg/transform_pipeline' describe InlineSvg::TransformPipeline::Transformations::DataAttributes do it "adds a data attribute to a SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::DataAttributes.create_with_value({some: "value"}) expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end it "dasherizes the data attribute name" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::DataAttributes.create_with_value({some_name: "value"}) expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end it "dasherizes a data attribute name with multiple parts" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::DataAttributes.create_with_value({some_other_name: "value"}) expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end context "when multiple data attributes are supplied" do it "adds data attributes to the SVG for each supplied value" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::DataAttributes. create_with_value({some: "value", other: "thing"}) expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end end context "when a non-hash is supplied" do it "does not update the SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::DataAttributes. create_with_value("some non-hash") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end end end ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/width_spec.rb������������������������0000644�0000041�0000041�00000000705�15145733677�027576� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg/transform_pipeline' describe InlineSvg::TransformPipeline::Transformations::Width do it "adds width attribute to a SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::Width.create_with_value("5%") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end end �����������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/aria_attributes_spec.rb��������������0000644�0000041�0000041�00000006463�15145733677�031650� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require "inline_svg/transform_pipeline" describe InlineSvg::TransformPipeline::Transformations::AriaAttributes do it "adds a role attribute to the SVG document" do document = Nokogiri::XML::Document.parse("Some document") transformation = InlineSvg::TransformPipeline::Transformations::AriaAttributes.create_with_value({}) expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end context "aria-labelledby attribute" do it "adds 'title' when a title element is present" do document = Nokogiri::XML::Document.parse("Some titleSome document") transformation = InlineSvg::TransformPipeline::Transformations::AriaAttributes.create_with_value(true) expect(InlineSvg::IdGenerator).to receive(:generate).with("title", "Some title"). and_return("some-id") expect(transformation.transform(document).to_html).to eq( "Some titleSome document\n" ) end it "adds 'desc' when a description element is present" do document = Nokogiri::XML::Document.parse("Some descriptionSome document") transformation = InlineSvg::TransformPipeline::Transformations::AriaAttributes.create_with_value(true) expect(InlineSvg::IdGenerator).to receive(:generate).with("desc", "Some description"). and_return("some-id") expect(transformation.transform(document).to_html).to eq( "Some descriptionSome document\n" ) end it "adds both 'desc' and 'title' when title and description elements are present" do document = Nokogiri::XML::Document.parse("Some titleSome descriptionSome document") transformation = InlineSvg::TransformPipeline::Transformations::AriaAttributes.create_with_value(true) expect(InlineSvg::IdGenerator).to receive(:generate).with("title", "Some title"). and_return("some-id") expect(InlineSvg::IdGenerator).to receive(:generate).with("desc", "Some description"). and_return("some-other-id") expect(transformation.transform(document).to_html).to eq( "Some title\nSome descriptionSome document\n" ) end it "uses existing IDs when they exist" do document = Nokogiri::XML::Document.parse("Some titleSome descriptionSome document") transformation = InlineSvg::TransformPipeline::Transformations::AriaAttributes.create_with_value(true) expect(InlineSvg::IdGenerator).to receive(:generate).with("my-title", "Some title"). and_return("some-id") expect(InlineSvg::IdGenerator).to receive(:generate).with("my-desc", "Some description"). and_return("some-other-id") expect(transformation.transform(document).to_html).to eq( "Some title\nSome descriptionSome document\n" ) end end end �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/title_spec.rb������������������������0000644�0000041�0000041�00000003041�15145733677�027574� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg/transform_pipeline' describe InlineSvg::TransformPipeline::Transformations::Title do it "adds a title element as the first element in the SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::Title.create_with_value("Some Title") expect(transformation.transform(document).to_html).to eq( "Some TitleSome document\n" ) end it "overwrites the content of an existing title element" do document = Nokogiri::XML::Document.parse('My TitleSome document') transformation = InlineSvg::TransformPipeline::Transformations::Title.create_with_value("Some Title") expect(transformation.transform(document).to_html).to eq( "Some TitleSome document\n" ) end it "handles empty SVG documents" do document = Nokogiri::XML::Document.parse('') transformation = InlineSvg::TransformPipeline::Transformations::Title.create_with_value("Some Title") expect(transformation.transform(document).to_html).to eq( "Some Title\n" ) end it "handles non-ASCII characters" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::Title.create_with_value("åäö") expect(transformation.transform(document).to_html).to eq( "åäöSome document\n" ) end end �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/style_attribute_spec.rb��������������0000644�0000041�0000041�00000001675�15145733677�031711� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require "inline_svg/transform_pipeline" describe InlineSvg::TransformPipeline::Transformations::ClassAttribute do it "adds a style attribute to a SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::StyleAttribute .create_with_value("padding: 10px") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end it "preserves existing style attributes on a SVG document" do xml = 'Some document' document = Nokogiri::XML::Document.parse(xml) transformation = InlineSvg::TransformPipeline::Transformations::StyleAttribute .create_with_value("padding: 10px") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end end �������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/size_spec.rb�������������������������0000644�0000041�0000041�00000001544�15145733677�027433� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg/transform_pipeline' describe InlineSvg::TransformPipeline::Transformations::Size do it "adds width and height attributes to a SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::Size.create_with_value("5% * 5%") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end it "adds the same width and height value when only passed one attribute" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::Size.create_with_value("5%") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end end ������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/height_spec.rb�����������������������0000644�0000041�0000041�00000001436�15145733677�027731� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg/transform_pipeline' describe InlineSvg::TransformPipeline::Transformations::Height do it "adds height attribute to a SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::Height.create_with_value("5%") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end it "handles documents without SVG root elements" do document = Nokogiri::XML::Document.parse("barSome document") transformation = InlineSvg::TransformPipeline::Transformations::Height.create_with_value("5%") expect(transformation.transform(document).to_html).to eq( "bar\n" ) end end ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/view_box_spec.rb���������������������0000644�0000041�0000041�00000000755�15145733677�030306� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg/transform_pipeline' describe InlineSvg::TransformPipeline::Transformations::ViewBox do it "adds viewBox attribute to a SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::ViewBox .create_with_value("0 0 100 100") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end end �������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/id_attribute_spec.rb�����������������0000644�0000041�0000041�00000000730�15145733677�031134� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg/transform_pipeline' describe InlineSvg::TransformPipeline::Transformations::IdAttribute do it "adds an id attribute to a SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::IdAttribute.create_with_value("some-id") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end end ����������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/preserve_aspect_ratio_spec.rb��������0000644�0000041�0000041�00000001022�15145733677�033040� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg/transform_pipeline' describe InlineSvg::TransformPipeline::Transformations::PreserveAspectRatio do it "adds preserveAspectRatio attribute to a SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::PreserveAspectRatio.create_with_value("xMaxYMax meet") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end end ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/class_attribute_spec.rb��������������0000644�0000041�0000041�00000001621�15145733677�031645� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require "inline_svg/transform_pipeline" describe InlineSvg::TransformPipeline::Transformations::ClassAttribute do it "adds a class attribute to a SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::ClassAttribute.create_with_value("some-class") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end it "preserves existing class attributes on a SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::ClassAttribute.create_with_value("some-class") expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end end ���������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/transformation_spec.rb���������������0000644�0000041�0000041�00000002657�15145733677�031535� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg' require 'inline_svg/transform_pipeline' describe InlineSvg::TransformPipeline::Transformations::Transformation do context "#with_svg" do it "returns a Nokogiri::XML::Document representing the parsed document fragment" do document = Nokogiri::XML::Document.parse("Some document") transformation = InlineSvg::TransformPipeline::Transformations::Transformation.new(:irrelevant) expect(transformation.with_svg(document).to_html).to eq( "Some document\n" ) end it "yields to the block when the document contains an SVG element" do document = Nokogiri::XML::Document.parse("Some document") svg = document.at_css("svg") transformation = InlineSvg::TransformPipeline::Transformations::Transformation.new(:irrelevant) returned_document = nil expect do |b| returned_document = transformation.with_svg(document, &b) end.to yield_control expect(returned_document.to_s).to match(/Some document<\/svg>/) end it "does not yield if the document does not contain an SVG element at the root" do document = Nokogiri::XML::Document.parse("barSome document") transformation = InlineSvg::TransformPipeline::Transformations::Transformation.new(:irrelevant) expect do |b| transformation.with_svg(document, &b) end.not_to yield_control end end end ���������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/description_spec.rb������������������0000644�0000041�0000041�00000002361�15145733677�031002� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg/transform_pipeline' describe InlineSvg::TransformPipeline::Transformations::Description do it "adds a desc element to the SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::Description.create_with_value("Some Description") expect(transformation.transform(document).to_html).to eq( "Some DescriptionSome document\n" ) end it "overwrites the content of an existing description element" do document = Nokogiri::XML::Document.parse('My DescriptionSome document') transformation = InlineSvg::TransformPipeline::Transformations::Description.create_with_value("Some Description") expect(transformation.transform(document).to_html).to eq( "Some DescriptionSome document\n" ) end it "handles empty SVG documents" do document = Nokogiri::XML::Document.parse('') transformation = InlineSvg::TransformPipeline::Transformations::Description.create_with_value("Some Description") expect(transformation.transform(document).to_html).to eq( "Some Description\n" ) end end �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/transformation_pipeline/transformations/aria_hidden_attribute_spec.rb��������0000644�0000041�0000041�00000000771�15145733677�032774� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg/transform_pipeline' describe InlineSvg::TransformPipeline::Transformations::AriaHiddenAttribute do it "adds an aria-hidden='true' attribute to a SVG document" do document = Nokogiri::XML::Document.parse('Some document') transformation = InlineSvg::TransformPipeline::Transformations::AriaHiddenAttribute.create_with_value(true) expect(transformation.transform(document).to_html).to eq( "Some document\n" ) end end �������inline_svg-1.10.0/spec/transformation_pipeline/transformations_spec.rb������������������������������0000644�0000041�0000041�00000011720�15145733677�026456� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require 'inline_svg' require 'inline_svg/transform_pipeline' class ACustomTransform < InlineSvg::CustomTransformation def transform(doc) doc end end class ASecondCustomTransform < ACustomTransform; end describe InlineSvg::TransformPipeline::Transformations do context "looking up transformations" do it "returns built-in transformations when parameters are supplied" do transformations = InlineSvg::TransformPipeline::Transformations.lookup( nocomment: 'irrelevant', class: 'irrelevant', style: 'irrelevant', title: 'irrelevant', desc: 'irrelevant', size: 'irrelevant', height: 'irrelevant', width: 'irrelevant', view_box: 'irrelevant', id: 'irrelevant', data: 'irrelevant', preserve_aspect_ratio: 'irrelevant', aria: 'irrelevant', aria_hidden: "true" ) expect(transformations.map(&:class)).to match_array([ InlineSvg::TransformPipeline::Transformations::NoComment, InlineSvg::TransformPipeline::Transformations::ClassAttribute, InlineSvg::TransformPipeline::Transformations::StyleAttribute, InlineSvg::TransformPipeline::Transformations::Title, InlineSvg::TransformPipeline::Transformations::Description, InlineSvg::TransformPipeline::Transformations::Size, InlineSvg::TransformPipeline::Transformations::Height, InlineSvg::TransformPipeline::Transformations::Width, InlineSvg::TransformPipeline::Transformations::ViewBox, InlineSvg::TransformPipeline::Transformations::IdAttribute, InlineSvg::TransformPipeline::Transformations::DataAttributes, InlineSvg::TransformPipeline::Transformations::PreserveAspectRatio, InlineSvg::TransformPipeline::Transformations::AriaAttributes, InlineSvg::TransformPipeline::Transformations::AriaHiddenAttribute ]) end it "returns transformations in priority order" do built_ins = { desc: { transform: InlineSvg::TransformPipeline::Transformations::Description, priority: 1 }, size: { transform: InlineSvg::TransformPipeline::Transformations::Size }, title: { transform: InlineSvg::TransformPipeline::Transformations::Title, priority: 2 } } allow(InlineSvg::TransformPipeline::Transformations).to \ receive(:built_in_transformations).and_return(built_ins) transformations = InlineSvg::TransformPipeline::Transformations.lookup( { desc: "irrelevant", size: "irrelevant", title: "irrelevant", } ) # Use `eq` here because we care about order expect(transformations.map(&:class)).to eq([ InlineSvg::TransformPipeline::Transformations::Description, InlineSvg::TransformPipeline::Transformations::Title, InlineSvg::TransformPipeline::Transformations::Size, ]) end it "returns no transformations when asked for an unknown transform" do transformations = InlineSvg::TransformPipeline::Transformations.lookup( not_a_real_transform: 'irrelevant' ) expect(transformations.map(&:class)).to match_array([]) end it "does not return a transformation when a value is not supplied" do transformations = InlineSvg::TransformPipeline::Transformations.lookup( title: nil ) expect(transformations.map(&:class)).to match_array([]) end end context "custom transformations" do before(:each) do InlineSvg.configure do |config| config.add_custom_transformation({transform: ACustomTransform, attribute: :my_transform, priority: 2}) config.add_custom_transformation({transform: ASecondCustomTransform, attribute: :my_other_transform, priority: 1}) end end after(:each) do InlineSvg.reset_configuration! end it "returns configured custom transformations" do transformations = InlineSvg::TransformPipeline::Transformations.lookup( my_transform: :irrelevant ) expect(transformations.map(&:class)).to match_array([ACustomTransform]) end it "returns configured custom transformations in priority order" do transformations = InlineSvg::TransformPipeline::Transformations.lookup( my_transform: :irrelevant, my_other_transform: :irrelevant ) # Use `eq` here because we care about order: expect(transformations.map(&:class)).to eq([ASecondCustomTransform, ACustomTransform]) end it "always prioritizes built-in transforms before custom transforms" do transformations = InlineSvg::TransformPipeline::Transformations.lookup( my_transform: :irrelevant, my_other_transform: :irrelevant, desc: "irrelevant" ) # Use `eq` here because we care about order: expect(transformations.map(&:class)).to eq( [ InlineSvg::TransformPipeline::Transformations::Description, ASecondCustomTransform, ACustomTransform ] ) end end end ������������������������������������������������inline_svg-1.10.0/spec/io_resource_spec.rb����������������������������������������������������������0000644�0000041�0000041�00000003524�15145733677�020613� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require_relative '../lib/inline_svg' require "stringio" require "tempfile" describe InlineSvg::IOResource do it "support api methods" do is_expected.to respond_to(:===, :read) end describe '#===' do context 'return true' do it "for IO object" do read_io, write_io = IO.pipe expect(subject === read_io).to be true expect(subject === write_io).to be true end it "for StringIO object" do expect(subject === StringIO.new).to be true end it "for File object" do expect(subject === File.new("#{Dir.tmpdir}/testfile", "w")).to be true end end context 'return false' do it "for String object" do expect(subject === "string/filename").to be false end end end describe '#read' do tests = proc do it "closed raise error" do rio.close expect do subject.read(rio) end.to raise_error(IOError) end it "empty" do rio.read expect(subject.read rio).to eq '' end it "twice" do expect(subject.read rio).to eq answer expect(subject.read rio).to eq answer end it "write only raise error" do expect do subject.read wio end.to raise_error(IOError) end end context 'IO object' do let(:answer) { 'read' } let(:rio) { StringIO.new(answer, 'r') } let(:wio) { StringIO.new('write', 'w') } instance_exec &tests end context 'File object' do let(:file_path) { File.expand_path('../files/example.svg', __FILE__) } let(:answer) { File.read(file_path) } let(:rio) { File.new(file_path, 'r') } let(:wio) { File.new('/dev/null', 'w') } instance_exec &tests it 'has non empty body' do expect(answer).to_not eq '' end end end end ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/spec/static_asset_finder_spec.rb��������������������������������������������������0000644�0000041�0000041�00000001702�15145733677�022306� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require_relative '../lib/inline_svg' describe InlineSvg::StaticAssetFinder do context "when the file is not found" do it "returns nil" do stub_const('Rails', double('Rails').as_null_object) expect(::Rails.application.config.assets).to receive(:compile).and_return(true) expect(described_class.find_asset('some-file').pathname).to be_nil end end context "when the file is found" do it "returns fully qualified file path from Sprockets" do stub_const('Rails', double('Rails').as_null_object) expect(::Rails.application.config.assets).to receive(:compile).and_return(true) pathname = Pathname.new('/full/path/to/some-file') asset = double('Asset') expect(asset).to receive(:filename).and_return(pathname) expect(::Rails.application.assets).to receive(:[]).with('some-file').and_return(asset) expect(described_class.find_asset('some-file').pathname).to eq(pathname) end end end ��������������������������������������������������������������inline_svg-1.10.0/Rakefile��������������������������������������������������������������������������0000644�0000041�0000041�00000000326�15145733677�015446� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������require "bundler/gem_tasks" require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) do |t| t.pattern = Dir.glob("spec/**/*_spec.rb") #t.rspec_opts = "--format documentation" end task :default => :spec ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/.rubocop_todo.yml�����������������������������������������������������������������0000644�0000041�0000041�00000033143�15145733677�017303� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This configuration was generated by # `rubocop --auto-gen-config` # on 2017-10-10 17:17:56 -0400 using RuboCop version 0.50.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 17 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: leading, trailing Layout/DotPosition: Exclude: - 'spec/finds_asset_paths_spec.rb' - 'spec/helpers/inline_svg_spec.rb' - 'spec/id_generator_spec.rb' - 'spec/transformation_pipeline/transformations/aria_attributes_spec.rb' - 'spec/transformation_pipeline/transformations/data_attributes_spec.rb' # Offense count: 2 # Cop supports --auto-correct. Layout/EmptyLineAfterMagicComment: Exclude: - 'inline_svg.gemspec' - 'spec/cached_asset_file_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: AllowAdjacentOneLineDefs, NumberOfEmptyLines. Layout/EmptyLineBetweenDefs: Exclude: - 'spec/inline_svg_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Layout/EmptyLinesAroundAccessModifier: Exclude: - 'lib/inline_svg/cached_asset_file.rb' # Offense count: 8 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: empty_lines, no_empty_lines Layout/EmptyLinesAroundBlockBody: Exclude: - 'spec/helpers/inline_svg_spec.rb' - 'spec/inline_svg_spec.rb' - 'spec/io_resource_spec.rb' - 'spec/transformation_pipeline/transformations_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines Layout/EmptyLinesAroundClassBody: Exclude: - 'lib/inline_svg.rb' # Offense count: 4 # Cop supports --auto-correct. # Configuration parameters: SupportedStyles, IndentationWidth. # SupportedStyles: special_inside_parentheses, consistent, align_brackets Layout/IndentArray: EnforcedStyle: consistent # Offense count: 11 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent Layout/IndentHeredoc: Exclude: - 'spec/helpers/inline_svg_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Layout/LeadingCommentSpace: Exclude: - 'Rakefile' # Offense count: 4 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. # SupportedStyles: aligned, indented, indented_relative_to_receiver Layout/MultilineMethodCallIndentation: Exclude: - 'spec/transformation_pipeline/transformations/data_attributes_spec.rb' - 'spec/transformation_pipeline/transformations/style_attribute_spec.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: SupportedStyles. # SupportedStyles: space, no_space Layout/SpaceAroundEqualsInParameterDefault: EnforcedStyle: no_space # Offense count: 8 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces, SpaceBeforeBlockParameters. # SupportedStyles: space, no_space # SupportedStylesForEmptyBraces: space, no_space Layout/SpaceInsideBlockBraces: Exclude: - 'lib/inline_svg/transform_pipeline/transformations.rb' # Offense count: 2 # Cop supports --auto-correct. Layout/SpaceInsideBrackets: Exclude: - 'lib/inline_svg.rb' # Offense count: 20 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces. # SupportedStyles: space, no_space, compact # SupportedStylesForEmptyBraces: space, no_space Layout/SpaceInsideHashLiteralBraces: Exclude: - 'spec/helpers/inline_svg_spec.rb' - 'spec/inline_svg_spec.rb' - 'spec/transformation_pipeline/transformations/data_attributes_spec.rb' - 'spec/transformation_pipeline/transformations_spec.rb' # Offense count: 4 # Cop supports --auto-correct. Layout/SpaceInsideParens: Exclude: - 'lib/inline_svg/transform_pipeline/transformations.rb' - 'spec/helpers/inline_svg_spec.rb' # Offense count: 3 # Cop supports --auto-correct. Layout/TrailingWhitespace: Exclude: - 'spec/io_resource_spec.rb' # Offense count: 2 Lint/AmbiguousOperator: Exclude: - 'spec/io_resource_spec.rb' # Offense count: 2 Lint/ShadowingOuterLocalVariable: Exclude: - 'lib/inline_svg/transform_pipeline/transformations/description.rb' - 'lib/inline_svg/transform_pipeline/transformations/title.rb' # Offense count: 1 # Cop supports --auto-correct. Lint/UnneededSplatExpansion: Exclude: - 'lib/inline_svg.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. Lint/UnusedBlockArgument: Exclude: - 'lib/inline_svg/railtie.rb' - 'lib/inline_svg/transform_pipeline/transformations.rb' # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods. Lint/UnusedMethodArgument: Exclude: - 'spec/inline_svg_spec.rb' # Offense count: 2 Lint/UselessAssignment: Exclude: - 'spec/cached_asset_file_spec.rb' - 'spec/transformation_pipeline/transformations/transformation_spec.rb' # Offense count: 1 Metrics/AbcSize: Max: 17 # Offense count: 20 # Configuration parameters: CountComments, ExcludedMethods. Metrics/BlockLength: Max: 169 # Offense count: 144 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Metrics/LineLength: Max: 183 # Offense count: 3 # Configuration parameters: CountComments. Metrics/MethodLength: Max: 14 # Offense count: 6 # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: snake_case, normalcase, non_integer Naming/VariableNumber: Exclude: - 'spec/cached_asset_file_spec.rb' # Offense count: 1 # Cop supports --auto-correct. Performance/StringReplacement: Exclude: - 'lib/inline_svg/transform_pipeline/transformations/data_attributes.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: always, conditionals Style/AndOr: Exclude: - 'lib/inline_svg/cached_asset_file.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, ProceduralMethods, FunctionalMethods, IgnoredMethods. # SupportedStyles: line_count_based, semantic, braces_for_chaining # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object # FunctionalMethods: let, let!, subject, watch # IgnoredMethods: lambda, proc, it Style/BlockDelimiters: Exclude: - 'lib/inline_svg/transform_pipeline/transformations.rb' # Offense count: 11 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: braces, no_braces, context_dependent Style/BracesAroundHashParameters: Exclude: - 'lib/inline_svg/transform_pipeline/transformations.rb' - 'spec/helpers/inline_svg_spec.rb' - 'spec/inline_svg_spec.rb' - 'spec/transformation_pipeline/transformations/data_attributes_spec.rb' - 'spec/transformation_pipeline/transformations_spec.rb' # Offense count: 6 Style/CaseEquality: Exclude: - 'lib/inline_svg/action_view/helpers.rb' - 'spec/io_resource_spec.rb' # Offense count: 14 # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: nested, compact Style/ClassAndModuleChildren: Exclude: - 'lib/inline_svg/transform_pipeline/transformations.rb' - 'lib/inline_svg/transform_pipeline/transformations/aria_attributes.rb' - 'lib/inline_svg/transform_pipeline/transformations/class_attribute.rb' - 'lib/inline_svg/transform_pipeline/transformations/data_attributes.rb' - 'lib/inline_svg/transform_pipeline/transformations/description.rb' - 'lib/inline_svg/transform_pipeline/transformations/height.rb' - 'lib/inline_svg/transform_pipeline/transformations/id_attribute.rb' - 'lib/inline_svg/transform_pipeline/transformations/no_comment.rb' - 'lib/inline_svg/transform_pipeline/transformations/preserve_aspect_ratio.rb' - 'lib/inline_svg/transform_pipeline/transformations/size.rb' - 'lib/inline_svg/transform_pipeline/transformations/style_attribute.rb' - 'lib/inline_svg/transform_pipeline/transformations/title.rb' - 'lib/inline_svg/transform_pipeline/transformations/transformation.rb' - 'lib/inline_svg/transform_pipeline/transformations/width.rb' # Offense count: 26 Style/Documentation: Enabled: false # Offense count: 1 # Cop supports --auto-correct. Style/EachWithObject: Exclude: - 'lib/inline_svg/transform_pipeline/transformations.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, AutoCorrectEncodingComment. # SupportedStyles: when_needed, always, never Style/Encoding: Exclude: - 'inline_svg.gemspec' # Offense count: 4 # Configuration parameters: MinBodyLength. Style/GuardClause: Exclude: - 'lib/inline_svg.rb' - 'lib/inline_svg/action_view/helpers.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys Style/HashSyntax: Exclude: - 'Rakefile' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: MaxLineLength. Style/IfUnlessModifier: Exclude: - 'lib/inline_svg/static_asset_finder.rb' - 'lib/inline_svg/transform_pipeline/transformations/aria_attributes.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: InverseMethods, InverseBlocks. Style/InverseMethods: Exclude: - 'lib/inline_svg/transform_pipeline/transformations.rb' # Offense count: 2 # Cop supports --auto-correct. Style/MutableConstant: Exclude: - 'lib/inline_svg/asset_file.rb' - 'lib/inline_svg/version.rb' # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: Whitelist. # Whitelist: be, be_a, be_an, be_between, be_falsey, be_kind_of, be_instance_of, be_truthy, be_within, eq, eql, end_with, include, match, raise_error, respond_to, start_with Style/NestedParenthesizedCalls: Exclude: - 'spec/io_resource_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: IncludeSemanticChanges. Style/NonNilCheck: Exclude: - 'lib/inline_svg/transform_pipeline/transformations.rb' # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: PreferredDelimiters. Style/PercentLiteralDelimiters: Exclude: - 'inline_svg.gemspec' # Offense count: 6 # Cop supports --auto-correct. # Configuration parameters: SupportedStyles. # SupportedStyles: compact, exploded Style/RaiseArgs: EnforcedStyle: compact # Offense count: 1 # Cop supports --auto-correct. Style/RedundantBegin: Exclude: - 'lib/inline_svg.rb' # Offense count: 8 # Cop supports --auto-correct. Style/RedundantSelf: Exclude: - 'lib/inline_svg/transform_pipeline/transformations/data_attributes.rb' - 'lib/inline_svg/transform_pipeline/transformations/height.rb' - 'lib/inline_svg/transform_pipeline/transformations/id_attribute.rb' - 'lib/inline_svg/transform_pipeline/transformations/preserve_aspect_ratio.rb' - 'lib/inline_svg/transform_pipeline/transformations/size.rb' - 'lib/inline_svg/transform_pipeline/transformations/transformation.rb' - 'lib/inline_svg/transform_pipeline/transformations/width.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes. # SupportedStyles: slashes, percent_r, mixed Style/RegexpLiteral: Exclude: - 'spec/transformation_pipeline/transformations/transformation_spec.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: use_perl_names, use_english_names Style/SpecialGlobalVars: Exclude: - 'inline_svg.gemspec' # Offense count: 280 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes Style/StringLiterals: Enabled: false # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: IgnoredMethods. # IgnoredMethods: respond_to, define_method Style/SymbolProc: Exclude: - 'lib/inline_svg/transform_pipeline/transformations/description.rb' - 'lib/inline_svg/transform_pipeline/transformations/no_comment.rb' - 'lib/inline_svg/transform_pipeline/transformations/title.rb' # Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyleForMultiline, SupportedStylesForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, no_comma Style/TrailingCommaInArguments: Exclude: - 'spec/transformation_pipeline/transformations_spec.rb' # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyleForMultiline, SupportedStylesForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, no_comma Style/TrailingCommaInLiteral: Exclude: - 'lib/inline_svg/transform_pipeline/transformations.rb' - 'spec/transformation_pipeline/transformations_spec.rb' # Offense count: 2 # Cop supports --auto-correct. Style/UnneededPercentQ: Exclude: - 'inline_svg.gemspec' �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/Gemfile���������������������������������������������������������������������������0000644�0000041�0000041�00000000137�15145733677�015274� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������source 'https://rubygems.org' # Specify your gem's dependencies in inline_svg.gemspec gemspec ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������inline_svg-1.10.0/README.md�������������������������������������������������������������������������0000644�0000041�0000041�00000026236�15145733677�015270� 0����������������������������������������������������������������������������������������������������ustar �www-data������������������������www-data���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Inline SVG ![Unit tests](https://github.com/jamesmartin/inline_svg/workflows/Ruby/badge.svg) ![Integration Tests](https://github.com/jamesmartin/inline_svg/workflows/Integration%20Tests/badge.svg) Styling a SVG document with CSS for use on the web is most reliably achieved by [adding classes to the document and embedding](http://css-tricks.com/using-svg/) it inline in the HTML. This gem adds Rails helper methods (`inline_svg_tag` and `inline_svg_pack_tag`) that read an SVG document (via Sprockets or Webpacker, so works with the Rails Asset Pipeline), applies a CSS class attribute to the root of the document and then embeds it into a view. Inline SVG supports: - [Rails 5](http://weblog.rubyonrails.org/2016/6/30/Rails-5-0-final/) (from [v0.10.0](https://github.com/jamesmartin/inline_svg/releases/tag/v0.10.0)) - [Rails 6](https://weblog.rubyonrails.org/2019/4/24/Rails-6-0-rc1-released/) with Sprockets or Webpacker (from [v1.5.2](https://github.com/jamesmartin/inline_svg/releases/tag/v1.5.2)). - [Rails 7](https://weblog.rubyonrails.org/2021/12/6/Rails-7-0-rc-1-released/) Inline SVG no longer officially supports Rails 3 or Rails 4 (although they may still work). In order to reduce the maintenance cost of this project we now follow the [Rails Maintenance Policy](https://guides.rubyonrails.org/maintenance_policy.html). ## Changelog This project adheres to [Semantic Versioning](http://semver.org). All notable changes are documented in the [CHANGELOG](https://github.com/jamesmartin/inline_svg/blob/master/CHANGELOG.md). ## Installation Add this line to your application's Gemfile: gem 'inline_svg' And then execute: $ bundle Or install it yourself as: $ gem install inline_svg ## Usage ```ruby # Sprockets inline_svg_tag(file_name, options={}) # Webpacker inline_svg_pack_tag(file_name, options={}) ``` _**Note:** The remainder of this README uses `inline_svg_tag` for examples, but the exact same principles work for `inline_svg_pack_tag`._ The `file_name` can be a full path to a file, the file's basename or an `IO` object. The actual path of the file on disk is resolved using [Sprockets](://github.com/sstephenson/sprockets) (when available), a naive file finder (`/public/assets/...`) or in the case of `IO` objects the SVG data is read from the object. This means you can pre-process and fingerprint your SVG files like other Rails assets, or choose to find SVG data yourself. Here's an example of embedding an SVG document and applying a 'class' attribute: ```erb Embedded SVG Documents<title> </head> <body> <h1>Embedded SVG Documents</h1> <div> <%= inline_svg_tag "some-document.svg", class: 'some-class' %> </div> </body> </html> ``` Here's some CSS to target the SVG, resize it and turn it an attractive shade of blue: ```css .some-class { display: block; margin: 0 auto; fill: #3498db; width: 5em; height: 5em; } ``` ## Options key | description :---------------------- | :---------- `id` | set a ID attribute on the SVG `class` | set a CSS class attribute on the SVG `style` | set a CSS style attribute on the SVG `data` | add data attributes to the SVG (supply as a hash) `size` | set width and height attributes on the SVG <br/> Can also be set using `height` and/or `width` attributes, which take precedence over `size` <br/> Supplied as "{Width} * {Height}" or "{Number}", so "30px\*45px" becomes `width="30px"` and `height="45px"`, and "50%" becomes `width="50%"` and `height="50%"` `title` | add a \<title\> node inside the top level of the SVG document `desc` | add a \<desc\> node inside the top level of the SVG document `nocomment` | remove comment tags from the SVG document `preserve_aspect_ratio` | adds a `preserveAspectRatio` attribute to the SVG `view_box` | adds a `viewBox` attribute to the SVG `aria` | adds common accessibility attributes to the SVG (see [PR #34](https://github.com/jamesmartin/inline_svg/pull/34#issue-152062674) for details) `aria_hidden` | adds the `aria-hidden=true` attribute to the SVG `fallback` | set fallback SVG document Example: ```ruby inline_svg_tag( "some-document.svg", id: 'some-id', class: 'some-class', data: {some: "value"}, size: '30% * 20%', title: 'Some Title', desc: 'Some description', nocomment: true, preserve_aspect_ratio: 'xMaxYMax meet', view_box: '0 0 100 100', aria: true, aria_hidden: true, fallback: 'fallback-document.svg' ) ``` ## Accessibility Use the `aria: true` option to make `inline_svg_tag` add the following accessibility (a11y) attributes to your embedded SVG: * Adds a `role="img"` attribute to the root SVG element * Adds a `aria-labelled-by="title-id desc-id"` attribute to the root SVG element, if the document contains `<title>` or `<desc>` elements Here's an example: ```erb <%= inline_svg_tag('iconmonstr-glasses-12-icon.svg', aria: true, title: 'An SVG', desc: 'This is my SVG. There are many like it. You get the picture') %> ``` ```xml <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" \ role="img" aria-labelledby="bx6wix4t9pxpwxnohrhrmms3wexsw2o m439lk7mopdzmouktv2o689pl59wmd2"> <title id="bx6wix4t9pxpwxnohrhrmms3wexsw2o">An SVG This is my SVG. There are many like it. You get the picture ``` ***Note:*** The title and desc `id` attributes generated for, and referenced by, `aria-labelled-by` are one-way digests based on the value of the title and desc elements and an optional "salt" value using the SHA1 algorithm. This reduces the chance of `inline_svg_tag` embedding elements inside the SVG with `id` attributes that clash with other elements elsewhere on the page. ## Custom Transformations The transformation behavior of `inline_svg_tag` can be customized by creating custom transformation classes. For example, inherit from `InlineSvg::CustomTransformation` and implement the `#transform` method: ```ruby # Sets the `custom` attribute on the root SVG element to supplied value # Remember to return a document, as this will be passed along the transformation chain class MyCustomTransform < InlineSvg::CustomTransformation def transform(doc) with_svg(doc) do |svg| svg["custom"] = value end end end ``` Add the custom configuration in an initializer (E.g. `./config/initializers/inline_svg.rb`): ```ruby # Note that the named `attribute` will be used to pass a value to your custom transform InlineSvg.configure do |config| config.add_custom_transformation(attribute: :my_custom_attribute, transform: MyCustomTransform) end ``` The custom transformation can then be called like so: ```haml %div = inline_svg_tag "some-document.svg", my_custom_attribute: 'some value' ``` In this example, the following transformation would be applied to a SVG document: ```xml ... ``` You can also provide a default_value to the custom transformation, so even if you don't pass a value it will be triggered ```ruby # Note that the named `attribute` will be used to pass a value to your custom transform InlineSvg.configure do |config| config.add_custom_transformation(attribute: :my_custom_attribute, transform: MyCustomTransform, default_value: 'default value') end ``` The custom transformation will be triggered even if you don't pass any attribute value ```haml %div = inline_svg_tag "some-document.svg" = inline_svg_tag "some-document.svg", my_custom_attribute: 'some value' ``` In this example, the following transformation would be applied to a SVG document: ```xml ... ``` And ```xml ... ``` Passing a `priority` option with your custom transformation allows you to control the order that transformations are applied to the SVG document: ```ruby InlineSvg.configure do |config| config.add_custom_transformation(attribute: :custom_one, transform: MyCustomTransform, priority: 1) config.add_custom_transformation(attribute: :custom_two, transform: MyOtherCustomTransform, priority: 2) end ``` Transforms are applied in ascending order (lowest number first). ***Note***: Custom transformations are always applied *after* all built-in transformations, regardless of priority. ## Custom asset file loader An asset file loader returns a `String` representing a SVG document given a filename. Custom asset loaders should be a Ruby object that responds to a method called `named`, that takes one argument (a string representing the filename of the SVG document). A simple example might look like this: ```ruby class MyAssetFileLoader def self.named(filename) # ... load SVG document however you like return "some document" end end ``` Configure your custom asset file loader in an initializer like so: ```ruby InlineSvg.configure do |config| config.asset_file = MyAssetFileLoader end ``` ## Caching all assets at boot time When your deployment strategy prevents dynamic asset file loading from disk it can be helpful to cache all possible SVG assets in memory at application boot time. In this case, you can configure the `InlineSvg::CachedAssetFile` to scan any number of paths on disks and load all the assets it finds into memory. For example, in this configuration we load every `*.svg` file found beneath the configured paths into memory: ```ruby InlineSvg.configure do |config| config.asset_file = InlineSvg::CachedAssetFile.new( paths: [ "#{Rails.root}/public/path/to/assets", "#{Rails.root}/public/other/path/to/assets" ], filters: /\.svg/ ) end ``` **Note:** Paths are read recursively, so think about keeping your SVG assets restricted to as few paths as possible, and using the filter option to further restrict assets to only those likely to be used by `inline_svg_tag`. ## Missing SVG Files If the specified SVG file cannot be found a helpful, empty SVG document is embedded into the page instead. The embedded document contains a single comment displaying the filename of the SVG image the helper tried to render: ```html ``` You may apply a class to this empty SVG document by specifying the following configuration: ```rb InlineSvg.configure do |config| config.svg_not_found_css_class = 'svg-not-found' end ``` Which would instead render: ```html ``` Alternatively, `inline_svg_tag` can be configured to raise an exception when a file is not found: ```ruby InlineSvg.configure do |config| config.raise_on_file_not_found = true end ``` ## Contributing 1. Fork it ( [http://github.com/jamesmartin/inline_svg/fork](http://github.com/jamesmartin/inline_svg/fork) ) 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request Please write tests for anything you change, add or fix. There is a [basic Rails app](http://github.com/jamesmartin/inline_svg_test_app) that demonstrates the gem's functionality in use. inline_svg-1.10.0/.rubocop.yml0000644000004100000410000000004015145733677016244 0ustar www-datawww-datainherit_from: .rubocop_todo.yml inline_svg-1.10.0/CHANGELOG.md0000644000004100000410000003162715145733677015622 0ustar www-datawww-data# Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased][unreleased] Nothing. ## [1.10.0] - 2024-09-03 ### Added - Support for Shakapacker. [#158](https://github.com/jamesmartin/inline_svg/pull/158). Thanks, [@tagliala](https://github.com/tagliala) ### Fixed - Fixed documentation typos. [#157](https://github.com/jamesmartin/inline_svg/pull/157). Thanks, [@tagliala](https://github.com/tagliala) - Fixed missing ActiveSupport require. [#152](https://github.com/jamesmartin/inline_svg/pull/152). Thanks, [@xymbol](https://github.com/xymbol) - Remove wrapping whitespace from SVG tags. [#150](https://github.com/jamesmartin/inline_svg/pull/150). Thanks, [@fredboyle](https://github.com/fredboyle) ## [1.9.0] - 2023-03-29 ### Added - A new option: `view_box` adds a `viewBox` attribute to the SVG. [#142](https://github.com/jamesmartin/inline_svg/pull/142). Thanks [@sunny](https://github.com/sunny) ### Fixed - Allow Propshaft assets to use fallbacks. [#140](https://github.com/jamesmartin/inline_svg/pull/140). Thanks, [@ohrite](https://github.com/ohrite) - Handling missing file when using static assets. [#141](https://github.com/jamesmartin/inline_svg/pull/141). Thanks, [@leighhalliday](https://github.com/leighhalliday) - Handle missing file when using Webpacker assets. ## [1.8.0] - 2022-01-09 ### Added - Remove deprecation warning for `inline_svg`, as we intend to keep it in 2.0. [#131](https://github.com/jamesmartin/inline_svg/pull/131). Thanks [@DanielJackson-Oslo](https://github.com/DanielJackson-Oslo) - Add support for Webpacker 6 beta. [#129](https://github.com/jamesmartin/inline_svg/pull/129). Thanks [@Intrepidd](https://github.com/Intrepidd) and [@tessi](https://github.com/tessi) - Add support for Propshaft assets in Rails 7. [#134](https://github.com/jamesmartin/inline_svg/pull/134). Thanks, [@martinzamuner](https://github.com/martinzamuner) ## [1.7.2] - 2020-12-07 ### Fixed - Improve performance of `CachedAssetFile`. [#118](https://github.com/jamesmartin/inline_svg/pull/118). Thanks [@stevendaniels](https://github.com/stevendaniels) - Avoid XSS by preventing malicious input of filenames. [#117](https://github.com/jamesmartin/inline_svg/pull/117). Thanks [@pbyrne](https://github.com/pbyrne). ## [1.7.1] - 2020-03-17 ### Fixed - Static Asset Finder uses pathname for compatibility with Sprockets 4+. [#106](https://github.com/jamesmartin/inline_svg/pull/106). Thanks [@subdigital](https://github.com/subdigital) ## [1.7.0] - 2020-02-13 ### Added - WebpackAssetFinder serves files from dev server if one is running. [#111](https://github.com/jamesmartin/inline_svg/pull/111). Thanks, [@connorshea](https://github.com/connorshea) ### Fixed - Using Webpacker and Asset Pipeline in a single App could result in SVGs not being found because the wrong `AssetFinder` was used. [#114](https://github.com/jamesmartin/inline_svg/pull/114). Thanks, [@kylefox](https://github.com/kylefox) - Prevent "EOFError error" when using webpack dev server over HTTPS [#113](https://github.com/jamesmartin/inline_svg/pull/113). Thanks, [@kylefox](https://github.com/kylefox) ## [1.6.0] - 2019-11-13 ### Added - Support Webpack via the new `inline_svg_pack_tag` helper and deprecate `inline_svg` helper in preparation for v2.0. [#103](https://github.com/jamesmartin/inline_svg/pull/103) Thanks, [@kylefox](https://github.com/kylefox) ## [1.5.2] - 2019-06-20 ### Fixed - Revert automatic Webpack asset finder behavior. Make Webpack "opt-in". [#98](https://github.com/jamesmartin/inline_svg/issues/98) ## [1.5.1] - 2019-06-18 ### Fixed - Prevent nil asset finder when neither Sprockets or Webpacker are available [#97](https://github.com/jamesmartin/inline_svg/issues/97) ## [1.5.0] - 2019-06-17 ### Added - Support for finding assets bundled by Webpacker [#96](https://github.com/jamesmartin/inline_svg/pull/96) ## [1.4.0] - 2019-04-19 ### Fixed - Prevent invalid XML names being generated via IdGenerator [#87](https://github.com/jamesmartin/inline_svg/issues/87) Thanks, [@endorfin](https://github.com/endorfin) ### Added - Raise error on file not found (if configured) [#93](https://github.com/jamesmartin/inline_svg/issues/93) ## [1.3.1] - 2017-12-14 ### Fixed - Allow Ruby < 2.1 to work with `CachedAssetFile` [#80](https://github.com/jamesmartin/inline_svg/pull/80) ## [1.3.0] - 2017-10-30 ### Added - Aria hidden attribute [#78](https://github.com/jamesmartin/inline_svg/pull/78) and [#79](https://github.com/jamesmartin/inline_svg/pull/79) - In-line CSS style attribute [#71](https://github.com/jamesmartin/inline_svg/pull/71) ### Fixed - Make aria ID attributes unique [#77](https://github.com/jamesmartin/inline_svg/pull/77) ## [1.2.3] - 2017-08-17 ### Fixed - Handle UTF-8 characters in SVG documents [#60](https://github.com/jamesmartin/inline_svg/pull/69) ## [1.2.2] - 2017-07-06 ### Fixed - Handle malformed documents that don't contain a root SVG element [#60](https://github.com/jamesmartin/inline_svg/pull/65) ### Added - Add configurable CSS class to empty SVG document [#67](https://github.com/jamesmartin/inline_svg/pull/67) ## [1.2.1] - 2017-05-02 ### Fixed - Select most exactly matching cached asset file when multiple files match given asset name [#64](https://github.com/jamesmartin/inline_svg/pull/64) ## [1.2.0] - 2017-04-20 ### Added - Cached asset file (load assets into memory at boot time) [#62](https://github.com/jamesmartin/inline_svg/pull/62) ## [1.1.0] - 2017-04-12 ### Added - Allow configurable asset file implementations [#61](https://github.com/jamesmartin/inline_svg/pull/61) ## [1.0.1] - 2017-04-10 ### Fixed - Don't override custom asset finders in Railtie ## [1.0.0] - 2017-04-7 ### Added - Remove dependency on `Loofah` while maintaining basic `nocomment` transform ## [0.12.1] - 2017-03-24 ### Added - Relax dependency on `Nokogiri` to allow users to upgrade to v1.7x, preventing exposure to [CVE-2016-4658](https://github.com/sparklemotion/nokogiri/issues/1615): [#59](https://github.com/jamesmartin/inline_svg/issues/59) ## [0.12.0] - 2017-03-16 ### Added - Relax dependency on `ActiveSupport` to allow Rails 3 applications to use the gem: [#54](https://github.com/jamesmartin/inline_svg/issues/54) ## [0.11.1] - 2016-11-22 ### Fixed - Dasherize data attribute names: [#51](https://github.com/jamesmartin/inline_svg/issues/51) - Prevent ID collisions between `desc` and `title` attrs: [#52](https://github.com/jamesmartin/inline_svg/pull/52) ## [0.11.0] - 2016-07-24 ### Added - Priority ordering for transformations ### Fixed - Prevent duplicate desc elements being created [#46](https://github.com/jamesmartin/inline_svg/issues/46) - Prevent class attributes being replaced [#44](https://github.com/jamesmartin/inline_svg/issues/44) ## [0.10.0] - 2016-07-24 ### Added - Rails 5 support [#43](https://github.com/jamesmartin/inline_svg/pull/43) - Support for `Sprockets::Asset` [#45](https://github.com/jamesmartin/inline_svg/pull/45) ## [0.9.1] - 2016-07-18 ### Fixed - Provide a hint when the .svg extension is omitted from the filename [#41](https://github.com/jamesmartin/inline_svg/issues/41) ## [0.9.0] - 2016-06-30 ### Fixed - Hashed IDs for desc and title elements in aria-labeled-by attribute [#38](https://github.com/jamesmartin/inline_svg/issues/38) ## [0.8.0] - 2016-05-23 ### Added - Default values for custom transformations [#36](https://github.com/jamesmartin/inline_svg/issues/36). Thanks, [@andrewaguiar](https://github.com/andrewaguiar) ## [0.7.0] - 2016-05-03 ### Added - Aria attributes transform (aria-labelledby / role etc.) Addresses issue [#28](https://github.com/jamesmartin/inline_svg/issues/28) ## [0.6.4] - 2016-04-23 ### Fixed - Don't duplicate the `title` element. Addresses issue [#31](https://github.com/jamesmartin/inline_svg/issues/31) - Make the `title` element the first child node of the SVG document ## [0.6.3] - 2016-04-19 ### Added - Accept `IO` objects as arguments to `inline_svg`. Thanks, [@ASnow](https://github.com/ASnow). ## [0.6.2] - 2016-01-24 ### Fixed - Support Sprockets >= 3.0 and config.assets.precompile = false ## [0.6.1] - 2015-08-06 ### Fixed - Support Rails versions back to 4.0.4. Thanks, @walidvb. ## [0.6.0] - 2015-07-07 ### Added - Apply user-supplied [custom transformations](https://github.com/jamesmartin/inline_svg/blob/master/README.md#custom-transformations) to a document. ## [0.5.3] - 2015-06-22 ### Added - `preserveAspectRatio` transformation on SVG root node. Thanks, @paulozoom. ## [0.5.2] - 2015-04-03 ### Fixed - Support Sprockets v2 and v3 (Sprockets::Asset no longer to_s to a filename) ## [0.5.1] - 2015-03-30 ### Warning ** This version is NOT compatible with Sprockets >= 3. ** ### Fixed - Support for ActiveSupport (and hence, Rails) 4.2.x. Thanks, @jmarceli. ## [0.5.0] - 2015-03-29 ### Added - A new option: `id` adds an id attribute to the SVG. - A new option: `data` adds data attributes to the SVG. ### Changed - New options: `height` and `width` override `size` and can be set independently. ## [0.4.0] - 2015-03-22 ### Added - A new option: `size` adds width and height attributes to an SVG. Thanks, @2metres. ### Changed - Dramatically simplified the TransformPipeline and Transformations code. - Added tests for the pipeline and new size transformations. ### Fixed - Transformations can no longer be created with a nil value. ## [0.3.0] - 2015-03-20 ### Added - Use Sprockets to find canonical asset paths (fingerprinted, post asset-pipeline). ## [0.2.0] - 2014-12-31 ### Added - Optionally remove comments from SVG files. Thanks, @jmarceli. ## [0.1.0] - 2014-12-15 ### Added - Optionally add a title and description to a document. Thanks, ludwig.schubert@qlearning.de. - Add integration tests for main view helper. Thanks, ludwig.schubert@qlearning.de. ## 0.0.1 - 2014-11-24 ### Added - Basic Railtie and view helper to inline SVG documents to Rails views. [unreleased]: https://github.com/jamesmartin/inline_svg/compare/v1.9.0...HEAD [1.9.0]: https://github.com/jamesmartin/inline_svg/compare/v1.8.0...v1.9.0 [1.8.0]: https://github.com/jamesmartin/inline_svg/compare/v1.7.2...v1.8.0 [1.7.2]: https://github.com/jamesmartin/inline_svg/compare/v1.7.1...v1.7.2 [1.7.1]: https://github.com/jamesmartin/inline_svg/compare/v1.7.0...v1.7.1 [1.7.0]: https://github.com/jamesmartin/inline_svg/compare/v1.6.0...v1.7.0 [1.6.0]: https://github.com/jamesmartin/inline_svg/compare/v1.5.2...v1.6.0 [1.5.2]: https://github.com/jamesmartin/inline_svg/compare/v1.5.1...v1.5.2 [1.5.1]: https://github.com/jamesmartin/inline_svg/compare/v1.5.0...v1.5.1 [1.5.0]: https://github.com/jamesmartin/inline_svg/compare/v1.4.0...v1.5.0 [1.4.0]: https://github.com/jamesmartin/inline_svg/compare/v1.3.1...v1.4.0 [1.3.1]: https://github.com/jamesmartin/inline_svg/compare/v1.3.0...v1.3.1 [1.3.0]: https://github.com/jamesmartin/inline_svg/compare/v1.2.3...v1.3.0 [1.2.3]: https://github.com/jamesmartin/inline_svg/compare/v1.2.2...v1.2.3 [1.2.2]: https://github.com/jamesmartin/inline_svg/compare/v1.2.1...v1.2.2 [1.2.1]: https://github.com/jamesmartin/inline_svg/compare/v1.2.0...v1.2.1 [1.2.0]: https://github.com/jamesmartin/inline_svg/compare/v1.1.0...v1.2.0 [1.1.0]: https://github.com/jamesmartin/inline_svg/compare/v1.0.1...v1.1.0 [1.0.1]: https://github.com/jamesmartin/inline_svg/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/jamesmartin/inline_svg/compare/v0.12.1...v1.0.0 [0.12.1]: https://github.com/jamesmartin/inline_svg/compare/v0.12.0...v0.12.1 [0.12.0]: https://github.com/jamesmartin/inline_svg/compare/v0.11.1...v0.12.0 [0.11.1]: https://github.com/jamesmartin/inline_svg/compare/v0.11.0...v0.11.1 [0.11.0]: https://github.com/jamesmartin/inline_svg/compare/v0.10.0...v0.11.0 [0.10.0]: https://github.com/jamesmartin/inline_svg/compare/v0.9.1...v0.10.0 [0.9.1]: https://github.com/jamesmartin/inline_svg/compare/v0.9.0...v0.9.1 [0.9.0]: https://github.com/jamesmartin/inline_svg/compare/v0.8.0...v0.9.0 [0.8.0]: https://github.com/jamesmartin/inline_svg/compare/v0.7.0...v0.8.0 [0.7.0]: https://github.com/jamesmartin/inline_svg/compare/v0.6.4...v0.7.0 [0.6.4]: https://github.com/jamesmartin/inline_svg/compare/v0.6.3...v0.6.4 [0.6.3]: https://github.com/jamesmartin/inline_svg/compare/v0.6.2...v0.6.3 [0.6.2]: https://github.com/jamesmartin/inline_svg/compare/v0.6.1...v0.6.2 [0.6.1]: https://github.com/jamesmartin/inline_svg/compare/v0.6.0...v0.6.1 [0.6.0]: https://github.com/jamesmartin/inline_svg/compare/v0.5.3...v0.6.0 [0.5.3]: https://github.com/jamesmartin/inline_svg/compare/v0.5.2...v0.5.3 [0.5.2]: https://github.com/jamesmartin/inline_svg/compare/v0.5.1...v0.5.2 [0.5.1]: https://github.com/jamesmartin/inline_svg/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/jamesmartin/inline_svg/compare/v0.4.0...v0.5.0 [0.4.0]: https://github.com/jamesmartin/inline_svg/compare/v0.3.0...v0.4.0 [0.3.0]: https://github.com/jamesmartin/inline_svg/compare/v0.2.0...v0.3.0 [0.2.0]: https://github.com/jamesmartin/inline_svg/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/jamesmartin/inline_svg/compare/v0.0.1...v0.1.0