inline_svg 0.11.0 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/integration_test.yml +58 -0
- data/.github/workflows/ruby.yml +20 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +421 -0
- data/CHANGELOG.md +144 -2
- data/README.md +148 -34
- data/Rakefile +7 -0
- data/inline_svg.gemspec +4 -4
- data/lib/inline_svg.rb +41 -9
- data/lib/inline_svg/action_view/helpers.rb +72 -7
- data/lib/inline_svg/cached_asset_file.rb +71 -0
- data/lib/inline_svg/finds_asset_paths.rb +1 -1
- data/lib/inline_svg/id_generator.rb +12 -3
- data/lib/inline_svg/io_resource.rb +4 -3
- data/lib/inline_svg/railtie.rb +8 -3
- data/lib/inline_svg/static_asset_finder.rb +4 -2
- data/lib/inline_svg/transform_pipeline.rb +0 -1
- data/lib/inline_svg/transform_pipeline/transformations.rb +8 -1
- data/lib/inline_svg/transform_pipeline/transformations/aria_attributes.rb +17 -20
- data/lib/inline_svg/transform_pipeline/transformations/aria_hidden.rb +9 -0
- data/lib/inline_svg/transform_pipeline/transformations/aria_hidden_attribute.rb +9 -0
- data/lib/inline_svg/transform_pipeline/transformations/class_attribute.rb +5 -6
- data/lib/inline_svg/transform_pipeline/transformations/data_attributes.rb +10 -5
- data/lib/inline_svg/transform_pipeline/transformations/description.rb +7 -6
- data/lib/inline_svg/transform_pipeline/transformations/height.rb +3 -4
- data/lib/inline_svg/transform_pipeline/transformations/id_attribute.rb +3 -4
- data/lib/inline_svg/transform_pipeline/transformations/no_comment.rb +5 -2
- data/lib/inline_svg/transform_pipeline/transformations/preserve_aspect_ratio.rb +3 -4
- data/lib/inline_svg/transform_pipeline/transformations/size.rb +4 -5
- data/lib/inline_svg/transform_pipeline/transformations/style_attribute.rb +11 -0
- data/lib/inline_svg/transform_pipeline/transformations/title.rb +7 -6
- data/lib/inline_svg/transform_pipeline/transformations/transformation.rb +13 -0
- data/lib/inline_svg/transform_pipeline/transformations/width.rb +3 -4
- data/lib/inline_svg/version.rb +1 -1
- data/lib/inline_svg/webpack_asset_finder.rb +50 -0
- data/spec/cached_asset_file_spec.rb +73 -0
- data/spec/files/static_assets/assets0/known-document-two.svg +1 -0
- data/spec/files/static_assets/assets0/known-document.svg +1 -0
- data/spec/files/static_assets/assets0/some-document.svg +1 -0
- data/spec/files/static_assets/assets1/known-document.svg +1 -0
- data/spec/files/static_assets/assets1/other-document.svg +3 -0
- data/spec/files/static_assets/assets1/some-file.txt +1 -0
- data/spec/helpers/inline_svg_spec.rb +104 -21
- data/spec/id_generator_spec.rb +5 -3
- data/spec/inline_svg_spec.rb +48 -0
- data/spec/transformation_pipeline/transformations/aria_attributes_spec.rb +16 -16
- data/spec/transformation_pipeline/transformations/aria_hidden_attribute_spec.rb +12 -0
- data/spec/transformation_pipeline/transformations/data_attributes_spec.rb +18 -0
- data/spec/transformation_pipeline/transformations/height_spec.rb +9 -0
- data/spec/transformation_pipeline/transformations/style_attribute_spec.rb +26 -0
- data/spec/transformation_pipeline/transformations/title_spec.rb +9 -0
- data/spec/transformation_pipeline/transformations/transformation_spec.rb +39 -0
- data/spec/transformation_pipeline/transformations_spec.rb +5 -1
- metadata +49 -22
- data/circle.yml +0 -3
data/inline_svg.gemspec
CHANGED
@@ -18,13 +18,13 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency "bundler", "~>
|
21
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_development_dependency "rspec", "~> 3.2"
|
24
24
|
spec.add_development_dependency "rspec_junit_formatter", "0.2.2"
|
25
25
|
spec.add_development_dependency "pry"
|
26
|
+
spec.add_development_dependency "rubocop"
|
26
27
|
|
27
|
-
spec.add_runtime_dependency "activesupport", ">=
|
28
|
-
spec.add_runtime_dependency "nokogiri", "
|
29
|
-
spec.add_runtime_dependency "loofah", ">= 2.0"
|
28
|
+
spec.add_runtime_dependency "activesupport", ">= 3.0"
|
29
|
+
spec.add_runtime_dependency "nokogiri", ">= 1.6"
|
30
30
|
end
|
data/lib/inline_svg.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require "inline_svg/version"
|
2
2
|
require "inline_svg/action_view/helpers"
|
3
3
|
require "inline_svg/asset_file"
|
4
|
+
require "inline_svg/cached_asset_file"
|
4
5
|
require "inline_svg/finds_asset_paths"
|
5
6
|
require "inline_svg/static_asset_finder"
|
7
|
+
require "inline_svg/webpack_asset_finder"
|
6
8
|
require "inline_svg/transform_pipeline"
|
7
9
|
require "inline_svg/io_resource"
|
8
10
|
|
@@ -14,24 +16,46 @@ module InlineSvg
|
|
14
16
|
class Configuration
|
15
17
|
class Invalid < ArgumentError; end
|
16
18
|
|
17
|
-
attr_reader :asset_finder, :custom_transformations
|
19
|
+
attr_reader :asset_file, :asset_finder, :custom_transformations, :svg_not_found_css_class
|
18
20
|
|
19
21
|
def initialize
|
20
22
|
@custom_transformations = {}
|
23
|
+
@asset_file = InlineSvg::AssetFile
|
24
|
+
@svg_not_found_css_class = nil
|
25
|
+
@raise_on_file_not_found = false
|
21
26
|
end
|
22
27
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def asset_file=(custom_asset_file)
|
29
|
+
begin
|
30
|
+
method = custom_asset_file.method(:named)
|
31
|
+
if method.arity == 1
|
32
|
+
@asset_file = custom_asset_file
|
33
|
+
else
|
34
|
+
raise InlineSvg::Configuration::Invalid.new("asset_file should implement the #named method with arity 1")
|
35
|
+
end
|
36
|
+
rescue NameError
|
37
|
+
raise InlineSvg::Configuration::Invalid.new("asset_file should implement the #named method")
|
31
38
|
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def asset_finder=(finder)
|
42
|
+
@asset_finder = if finder.respond_to?(:find_asset)
|
43
|
+
finder
|
44
|
+
else
|
45
|
+
# fallback to a naive static asset finder
|
46
|
+
# (sprokects >= 3.0 && config.assets.precompile = false
|
47
|
+
# See: https://github.com/jamesmartin/inline_svg/issues/25
|
48
|
+
InlineSvg::StaticAssetFinder
|
49
|
+
end
|
32
50
|
asset_finder
|
33
51
|
end
|
34
52
|
|
53
|
+
def svg_not_found_css_class=(css_class)
|
54
|
+
if css_class.present? && css_class.is_a?(String)
|
55
|
+
@svg_not_found_css_class = css_class
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
35
59
|
def add_custom_transformation(options)
|
36
60
|
if incompatible_transformation?(options.fetch(:transform))
|
37
61
|
raise InlineSvg::Configuration::Invalid.new("#{options.fetch(:transform)} should implement the .create_with_value and #transform methods")
|
@@ -39,6 +63,14 @@ module InlineSvg
|
|
39
63
|
@custom_transformations.merge!(Hash[ *[options.fetch(:attribute, :no_attribute), options] ])
|
40
64
|
end
|
41
65
|
|
66
|
+
def raise_on_file_not_found=(value)
|
67
|
+
@raise_on_file_not_found = value
|
68
|
+
end
|
69
|
+
|
70
|
+
def raise_on_file_not_found?
|
71
|
+
!!@raise_on_file_not_found
|
72
|
+
end
|
73
|
+
|
42
74
|
private
|
43
75
|
|
44
76
|
def incompatible_transformation?(klass)
|
@@ -4,21 +4,86 @@ require 'action_view/context' if defined?(Rails)
|
|
4
4
|
module InlineSvg
|
5
5
|
module ActionView
|
6
6
|
module Helpers
|
7
|
+
def inline_svg_tag(filename, transform_params={})
|
8
|
+
with_asset_finder(InlineSvg.configuration.asset_finder) do
|
9
|
+
render_inline_svg(filename, transform_params)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def inline_svg_pack_tag(filename, transform_params={})
|
14
|
+
with_asset_finder(InlineSvg::WebpackAssetFinder) do
|
15
|
+
render_inline_svg(filename, transform_params)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
7
19
|
def inline_svg(filename, transform_params={})
|
20
|
+
ActiveSupport::Deprecation.warn(
|
21
|
+
'`inline_svg` is deprecated and will be removed from inline_svg 2.0 (use `inline_svg_tag` or `inline_svg_pack_tag` instead)'
|
22
|
+
)
|
23
|
+
|
24
|
+
render_inline_svg(filename, transform_params)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def backwards_compatible_html_escape(filename)
|
30
|
+
# html_escape_once was introduced in newer versions of Rails.
|
31
|
+
if ERB::Util.respond_to?(:html_escape_once)
|
32
|
+
ERB::Util.html_escape_once(filename)
|
33
|
+
else
|
34
|
+
ERB::Util.html_escape(filename)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def render_inline_svg(filename, transform_params={})
|
8
39
|
begin
|
9
|
-
svg_file =
|
10
|
-
|
11
|
-
|
12
|
-
|
40
|
+
svg_file = read_svg(filename)
|
41
|
+
rescue InlineSvg::AssetFile::FileNotFound => error
|
42
|
+
raise error if InlineSvg.configuration.raise_on_file_not_found?
|
43
|
+
return placeholder(filename) unless transform_params[:fallback].present?
|
44
|
+
|
45
|
+
if transform_params[:fallback].present?
|
46
|
+
begin
|
47
|
+
svg_file = read_svg(transform_params[:fallback])
|
48
|
+
rescue InlineSvg::AssetFile::FileNotFound
|
49
|
+
placeholder(filename)
|
50
|
+
end
|
13
51
|
end
|
14
|
-
rescue InlineSvg::AssetFile::FileNotFound
|
15
|
-
return "<svg><!-- SVG file not found: '#{filename}' #{extension_hint(filename)}--></svg>".html_safe
|
16
52
|
end
|
17
53
|
|
18
54
|
InlineSvg::TransformPipeline.generate_html_from(svg_file, transform_params).html_safe
|
19
55
|
end
|
20
56
|
|
21
|
-
|
57
|
+
def read_svg(filename)
|
58
|
+
if InlineSvg::IOResource === filename
|
59
|
+
InlineSvg::IOResource.read filename
|
60
|
+
else
|
61
|
+
configured_asset_file.named filename
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def placeholder(filename)
|
66
|
+
css_class = InlineSvg.configuration.svg_not_found_css_class
|
67
|
+
not_found_message = "'#{backwards_compatible_html_escape(filename)}' #{extension_hint(filename)}"
|
68
|
+
|
69
|
+
if css_class.nil?
|
70
|
+
return "<svg><!-- SVG file not found: #{not_found_message}--></svg>".html_safe
|
71
|
+
else
|
72
|
+
return "<svg class='#{css_class}'><!-- SVG file not found: #{not_found_message}--></svg>".html_safe
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def configured_asset_file
|
77
|
+
InlineSvg.configuration.asset_file
|
78
|
+
end
|
79
|
+
|
80
|
+
def with_asset_finder(asset_finder)
|
81
|
+
Thread.current[:inline_svg_asset_finder] = asset_finder
|
82
|
+
output = yield
|
83
|
+
Thread.current[:inline_svg_asset_finder] = nil
|
84
|
+
|
85
|
+
output
|
86
|
+
end
|
22
87
|
|
23
88
|
def extension_hint(filename)
|
24
89
|
filename.ends_with?(".svg") ? "" : "(Try adding .svg to your filename) "
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module InlineSvg
|
4
|
+
class CachedAssetFile
|
5
|
+
attr_reader :assets, :filters, :paths
|
6
|
+
|
7
|
+
# For each of the given paths, recursively reads each asset and stores its
|
8
|
+
# contents alongside the full path to the asset.
|
9
|
+
#
|
10
|
+
# paths - One or more String representing directories on disk to search
|
11
|
+
# for asset files. Note: paths are searched recursively.
|
12
|
+
# filters - One or more Strings/Regexps to match assets against. Only
|
13
|
+
# assets matching all filters will be cached and available to load.
|
14
|
+
# Note: Specifying no filters will cache every file found in
|
15
|
+
# paths.
|
16
|
+
#
|
17
|
+
def initialize(paths: [], filters: [])
|
18
|
+
@paths = Array(paths).compact.map { |p| Pathname.new(p) }
|
19
|
+
@filters = Array(filters).map { |f| Regexp.new(f) }
|
20
|
+
@assets = @paths.reduce({}) { |assets, p| assets.merge(read_assets(assets, p)) }
|
21
|
+
@sorted_asset_keys = assets.keys.sort { |a, b| a.size <=> b.size }
|
22
|
+
end
|
23
|
+
|
24
|
+
# Public: Finds the named asset and returns the contents as a string.
|
25
|
+
#
|
26
|
+
# asset_name - A string representing the name of the asset to load
|
27
|
+
#
|
28
|
+
# Returns: A String or raises InlineSvg::AssetFile::FileNotFound error
|
29
|
+
def named(asset_name)
|
30
|
+
assets[key_for_asset(asset_name)] or
|
31
|
+
raise InlineSvg::AssetFile::FileNotFound.new("Asset not found: #{asset_name}")
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
# Internal: Finds the key for a given asset name (using a Regex). In the
|
36
|
+
# event of an ambiguous asset_name matching multiple assets, this method
|
37
|
+
# ranks the matches by their full file path, choosing the shortest (most
|
38
|
+
# exact) match over all others.
|
39
|
+
#
|
40
|
+
# Returns a String representing the key for the named asset or nil if there
|
41
|
+
# is no match.
|
42
|
+
def key_for_asset(asset_name)
|
43
|
+
@sorted_asset_keys.find { |k| k.include?(asset_name) }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Internal: Recursively descends through current_paths reading each file it
|
47
|
+
# finds and adding them to the accumulator if the fullpath of the file
|
48
|
+
# matches all configured filters.
|
49
|
+
#
|
50
|
+
# acc - Hash representing the accumulated assets keyed by full path
|
51
|
+
# paths - Pathname representing the current node in the directory
|
52
|
+
# structure to consider
|
53
|
+
#
|
54
|
+
# Returns a Hash containing the contents of each asset, keyed by fullpath
|
55
|
+
# to the asset.
|
56
|
+
def read_assets(acc, paths)
|
57
|
+
paths.each_child do |child|
|
58
|
+
if child.directory?
|
59
|
+
read_assets(acc, child)
|
60
|
+
elsif child.readable_real?
|
61
|
+
acc[child.to_s] = File.read(child) if matches_all_filters?(child)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
acc
|
65
|
+
end
|
66
|
+
|
67
|
+
def matches_all_filters?(path)
|
68
|
+
filters.all? { |f| f.match(path.to_s) }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -1,8 +1,17 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
1
3
|
module InlineSvg
|
2
4
|
class IdGenerator
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
class Randomness
|
6
|
+
require "securerandom"
|
7
|
+
def self.call
|
8
|
+
SecureRandom.hex(10)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.generate(base, salt, randomness: Randomness)
|
13
|
+
bytes = Digest::SHA1.digest("#{base}-#{salt}-#{randomness.call}")
|
14
|
+
'a' + Digest.hexencode(bytes).to_i(16).to_s(36)
|
6
15
|
end
|
7
16
|
end
|
8
17
|
end
|
@@ -1,16 +1,17 @@
|
|
1
1
|
module InlineSvg
|
2
2
|
module IOResource
|
3
|
-
def self.===
|
3
|
+
def self.===(object)
|
4
4
|
object.is_a?(IO) || object.is_a?(StringIO)
|
5
5
|
end
|
6
6
|
|
7
|
-
def self.default_for
|
7
|
+
def self.default_for(object)
|
8
8
|
case object
|
9
9
|
when StringIO then ''
|
10
10
|
when IO then 1
|
11
11
|
end
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
|
+
def self.read(object)
|
14
15
|
start = object.pos
|
15
16
|
str = object.read
|
16
17
|
object.seek start
|
data/lib/inline_svg/railtie.rb
CHANGED
@@ -10,9 +10,14 @@ module InlineSvg
|
|
10
10
|
|
11
11
|
config.after_initialize do |app|
|
12
12
|
InlineSvg.configure do |config|
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
13
|
+
# Configure the asset_finder:
|
14
|
+
# Only set this when a user-configured asset finder has not been
|
15
|
+
# configured already.
|
16
|
+
if config.asset_finder.nil?
|
17
|
+
# In default Rails apps, this will be a fully operational
|
18
|
+
# Sprockets::Environment instance
|
19
|
+
config.asset_finder = app.instance_variable_get(:@assets)
|
20
|
+
end
|
16
21
|
end
|
17
22
|
end
|
18
23
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
1
3
|
# Naive fallback asset finder for when sprockets >= 3.0 &&
|
2
4
|
# config.assets.precompile = false
|
3
5
|
# Thanks to @ryanswood for the original code:
|
4
|
-
# https://github.com/
|
6
|
+
# https://github.com/jamesmartin/inline_svg/commit/661bbb3bef7d1b4bd6ccd63f5f018305797b9509
|
5
7
|
module InlineSvg
|
6
8
|
class StaticAssetFinder
|
7
9
|
def self.find_asset(filename)
|
@@ -14,7 +16,7 @@ module InlineSvg
|
|
14
16
|
|
15
17
|
def pathname
|
16
18
|
if ::Rails.application.config.assets.compile
|
17
|
-
::Rails.application.assets[@filename].
|
19
|
+
Pathname.new(::Rails.application.assets[@filename].filename)
|
18
20
|
else
|
19
21
|
manifest = ::Rails.application.assets_manifest
|
20
22
|
asset_path = manifest.assets[@filename]
|
@@ -6,7 +6,9 @@ module InlineSvg::TransformPipeline::Transformations
|
|
6
6
|
desc: { transform: Description, priority: 2 },
|
7
7
|
title: { transform: Title, priority: 3 },
|
8
8
|
aria: { transform: AriaAttributes },
|
9
|
+
aria_hidden: { transform: AriaHiddenAttribute },
|
9
10
|
class: { transform: ClassAttribute },
|
11
|
+
style: { transform: StyleAttribute },
|
10
12
|
data: { transform: DataAttributes },
|
11
13
|
height: { transform: Height },
|
12
14
|
nocomment: { transform: NoComment },
|
@@ -38,8 +40,11 @@ module InlineSvg::TransformPipeline::Transformations
|
|
38
40
|
end
|
39
41
|
|
40
42
|
def self.lookup(transform_params)
|
43
|
+
return [] unless transform_params.any? || custom_transformations.any?
|
44
|
+
|
45
|
+
transform_params_with_defaults = params_with_defaults(transform_params)
|
41
46
|
all_transformations.map { |name, definition|
|
42
|
-
value =
|
47
|
+
value = transform_params_with_defaults[name]
|
43
48
|
definition.fetch(:transform, no_transform).create_with_value(value) if value
|
44
49
|
}.compact
|
45
50
|
end
|
@@ -72,6 +77,7 @@ end
|
|
72
77
|
require 'inline_svg/transform_pipeline/transformations/transformation'
|
73
78
|
require 'inline_svg/transform_pipeline/transformations/no_comment'
|
74
79
|
require 'inline_svg/transform_pipeline/transformations/class_attribute'
|
80
|
+
require 'inline_svg/transform_pipeline/transformations/style_attribute'
|
75
81
|
require 'inline_svg/transform_pipeline/transformations/title'
|
76
82
|
require 'inline_svg/transform_pipeline/transformations/description'
|
77
83
|
require 'inline_svg/transform_pipeline/transformations/size'
|
@@ -81,3 +87,4 @@ require 'inline_svg/transform_pipeline/transformations/id_attribute'
|
|
81
87
|
require 'inline_svg/transform_pipeline/transformations/data_attributes'
|
82
88
|
require 'inline_svg/transform_pipeline/transformations/preserve_aspect_ratio'
|
83
89
|
require 'inline_svg/transform_pipeline/transformations/aria_attributes'
|
90
|
+
require "inline_svg/transform_pipeline/transformations/aria_hidden_attribute"
|
@@ -1,34 +1,31 @@
|
|
1
1
|
module InlineSvg::TransformPipeline::Transformations
|
2
2
|
class AriaAttributes < Transformation
|
3
3
|
def transform(doc)
|
4
|
-
doc
|
5
|
-
|
4
|
+
with_svg(doc) do |svg|
|
5
|
+
# Add role
|
6
|
+
svg["role"] = "img"
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
# Build aria-labelledby string
|
9
|
+
aria_elements = []
|
10
|
+
svg.search("title").each do |element|
|
11
|
+
aria_elements << element["id"] = element_id_for("title", element)
|
12
|
+
end
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
aria_elements << element['id'] = element_id_for("title", element)
|
14
|
-
end
|
15
|
-
|
16
|
-
doc.search("svg desc").each do |element|
|
17
|
-
aria_elements << element['id'] = element_id_for("desc", element)
|
18
|
-
end
|
14
|
+
svg.search("desc").each do |element|
|
15
|
+
aria_elements << element["id"] = element_id_for("desc", element)
|
16
|
+
end
|
19
17
|
|
20
|
-
|
21
|
-
|
18
|
+
if aria_elements.any?
|
19
|
+
svg["aria-labelledby"] = aria_elements.join(" ")
|
20
|
+
end
|
22
21
|
end
|
23
|
-
|
24
|
-
doc
|
25
22
|
end
|
26
23
|
|
27
24
|
def element_id_for(base, element)
|
28
|
-
if element[
|
29
|
-
InlineSvg::IdGenerator.generate(base,
|
25
|
+
if element["id"].nil?
|
26
|
+
InlineSvg::IdGenerator.generate(base, element.text)
|
30
27
|
else
|
31
|
-
InlineSvg::IdGenerator.generate(element[
|
28
|
+
InlineSvg::IdGenerator.generate(element["id"], element.text)
|
32
29
|
end
|
33
30
|
end
|
34
31
|
end
|