svg_optimizer 0.2.2 → 0.2.6

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.

Potentially problematic release.


This version of svg_optimizer might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8b58103eace64dcab3740e83ce4a1c328dd6ae06
4
- data.tar.gz: 68ee27f69693afcd6eab21e0b1ffa57905d1c90b
2
+ SHA256:
3
+ metadata.gz: 385024a89793a95b04290dbea791b71007a8d27387a02939865f4ed6f2528c72
4
+ data.tar.gz: 8e1e9581f7516362b09bc2221a889043e3ae1b1ad442e73a7b178be26e3e1d8b
5
5
  SHA512:
6
- metadata.gz: '08e57257160f937494ee265a804e887033e59246d1e5a74b903ba99d8a5b4bc47687fd0e0ad9f1affa4afee2c6aa4bbd0d37c1ef5be1fe2d0036473f83c983b5'
7
- data.tar.gz: f6b6caf4b7ff9f4ae069d23a1c22267e55cde26d134fc2368ff5f26efabd767e03687a1e1c21060a9313124e12c14809498e9128f2dd72201fb71e1830fc7a57
6
+ metadata.gz: 699299880bf18dab73133899f59dcfa541a46ab45f3f0d2aeb48eb478caec60bdc2ce07c5093b5ab99e6c09118a966fa1009ba656ac7db0ef768a22a54774222
7
+ data.tar.gz: 1862ba8ad388c1523d7e69ff2e139efef59e4d3ede808d6ac9cabfd112c94b35a706563b1efaf10302386acce25812b02ba2b33ba3a2ab3bb45dc459963748d8
File without changes
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # SvgOptimizer
2
2
 
3
- [![Travis-CI](https://travis-ci.org/fnando/svg_optimizer.svg)](https://travis-ci.org/fnando/svg_optimizer)
3
+ [![Tests](https://github.com/fnando/svg_optimizer/workflows/ruby-tests/badge.svg)](https://github.com/fnando/svg_optimizer)
4
4
  [![Code Climate](https://codeclimate.com/github/fnando/svg_optimizer/badges/gpa.svg)](https://codeclimate.com/github/fnando/svg_optimizer)
5
- [![Test Coverage](https://codeclimate.com/github/fnando/svg_optimizer/badges/coverage.svg)](https://codeclimate.com/github/fnando/svg_optimizer/coverage)
6
5
  [![Gem](https://img.shields.io/gem/v/svg_optimizer.svg)](https://rubygems.org/gems/svg_optimizer)
7
6
  [![Gem](https://img.shields.io/gem/dt/svg_optimizer.svg)](https://rubygems.org/gems/svg_optimizer)
8
7
 
@@ -10,17 +9,15 @@ Some small optimizations for SVG files.
10
9
 
11
10
  ## Installation
12
11
 
13
- Add this line to your application's Gemfile:
14
-
15
- gem 'svg_optimizer'
16
-
17
- And then execute:
18
-
19
- $ bundle
12
+ ```bash
13
+ gem install svg_optimizer
14
+ ```
20
15
 
21
- Or install it yourself as:
16
+ Or add the following line to your project's Gemfile:
22
17
 
23
- $ gem install svg_optimizer
18
+ ```ruby
19
+ gem "svg_optimizer"
20
+ ```
24
21
 
25
22
  ## Usage
26
23
 
@@ -53,16 +50,34 @@ class MyPlugin < SvgOptimizer::Plugins::Base
53
50
  end
54
51
  ```
55
52
 
56
- The default list of plugins is stored at `SvgOptimizer::DEFAULT_PLUGINS`. To use your new plugin, just do something like this:
53
+ The default list of plugins is stored at `SvgOptimizer::DEFAULT_PLUGINS`. To use
54
+ your new plugin, just do something like this:
57
55
 
58
56
  ```ruby
59
57
  SvgOptimizer.optimize(xml, SvgOptimizer::DEFAULT_PLUGINS + [MyPlugin])
60
58
  ```
61
59
 
60
+ ## Maintainer
61
+
62
+ - [Nando Vieira](https://github.com/fnando)
63
+
64
+ ## Contributors
65
+
66
+ - https://github.com/fnando/svg_optimizer/contributors
67
+
62
68
  ## Contributing
63
69
 
64
- 1. Fork it
65
- 2. Create your feature branch (`git checkout -b my-new-feature`)
66
- 3. Commit your changes (`git commit -am 'Add some feature'`)
67
- 4. Push to the branch (`git push origin my-new-feature`)
68
- 5. Create new Pull Request
70
+ For more details about how to contribute, please read
71
+ https://github.com/fnando/svg_optimizer/blob/main/CONTRIBUTING.md.
72
+
73
+ ## License
74
+
75
+ The gem is available as open source under the terms of the
76
+ [MIT License](https://opensource.org/licenses/MIT). A copy of the license can be
77
+ found at https://github.com/fnando/svg_optimizer/blob/main/LICENSE.md.
78
+
79
+ ## Code of Conduct
80
+
81
+ Everyone interacting in the svg_optimizer project's codebases, issue trackers,
82
+ chat rooms and mailing lists is expected to follow the
83
+ [code of conduct](https://github.com/fnando/svg_optimizer/blob/main/CODE_OF_CONDUCT.md).
@@ -9,7 +9,7 @@ module SvgOptimizer
9
9
  ].freeze
10
10
 
11
11
  IDS = LETTERS.dup.concat(LETTERS.combination(2).to_a).freeze
12
- XLINK_NAMESPACE = "http://www.w3.org/1999/xlink".freeze
12
+ XLINK_NAMESPACE = "http://www.w3.org/1999/xlink"
13
13
 
14
14
  def ids
15
15
  @ids ||= IDS.dup
@@ -19,6 +19,10 @@ module SvgOptimizer
19
19
  # If there's a <script> or <style>, don't mess with ids.
20
20
  return if xml.css("script, style").any?
21
21
 
22
+ # SVG can have ids as arrays.
23
+ # Skip id optimization if that's the case.
24
+ return if xml.css("[id^='[']").size.nonzero?
25
+
22
26
  # Replace the ids otherwise.
23
27
  xml.css("[id]").each(&method(:cleanup_id))
24
28
  end
@@ -3,50 +3,55 @@
3
3
  module SvgOptimizer
4
4
  module Plugins
5
5
  class RemoveEditorNamespace < Base
6
- NAMESPACES = %w[
7
- http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd
8
- http://www.inkscape.org/namespaces/inkscape
9
- http://ns.adobe.com/AdobeIllustrator/10.0/
10
- http://ns.adobe.com/Graphs/1.0/
11
- http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/
12
- http://ns.adobe.com/Variables/1.0/
13
- http://ns.adobe.com/SaveForWeb/1.0/
14
- http://ns.adobe.com/Extensibility/1.0/
15
- http://ns.adobe.com/Flows/1.0/
16
- http://ns.adobe.com/ImageReplacement/1.0/
17
- http://ns.adobe.com/GenericCustomNamespace/1.0/
18
- http://ns.adobe.com/XPath/1.0
19
- http://www.bohemiancoding.com/sketch/ns
6
+ NAMESPACES = [
7
+ "http://ns.adobe.com/AdobeIllustrator/10.0/",
8
+ "http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/",
9
+ "http://ns.adobe.com/Extensibility/1.0/",
10
+ "http://ns.adobe.com/Flows/1.0/",
11
+ "http://ns.adobe.com/GenericCustomNamespace/1.0/",
12
+ "http://ns.adobe.com/Graphs/1.0/",
13
+ "http://ns.adobe.com/ImageReplacement/1.0/",
14
+ "http://ns.adobe.com/SaveForWeb/1.0/",
15
+ "http://ns.adobe.com/Variables/1.0/",
16
+ "http://ns.adobe.com/XPath/1.0",
17
+ "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd",
18
+ "http://www.bohemiancoding.com/sketch/ns",
19
+ "http://www.inkscape.org/namespaces/inkscape"
20
20
  ].freeze
21
21
 
22
22
  def process
23
- namespaces = xml.namespaces
24
- remove_namespaced_attributes
25
- xml.remove_namespaces!
23
+ xml.namespaces.each do |full_name, href|
24
+ _, name = full_name.split(":")
25
+ next unless NAMESPACES.include?(href)
26
26
 
27
- namespaces.each do |name, value|
28
- next if NAMESPACES.include?(value)
27
+ remove_namespaced_attributes(name, href)
28
+ end
29
29
 
30
- _, name = name.split(":")
31
- xml.root.add_namespace name, value
30
+ xml.root.namespace_definitions.each do |namespace|
31
+ remove_namespace(namespace) if NAMESPACES.include?(namespace.href)
32
32
  end
33
33
  end
34
34
 
35
- def namespaces_to_be_removed
36
- xml.namespaces.map do |name, value|
37
- _, name = name.split(":")
38
- name if NAMESPACES.include?(value)
39
- end.compact
35
+ def remove_namespaced_attributes(name, href)
36
+ xml.xpath("//@*[namespace-uri()='#{href}']").each do |node|
37
+ remove_matching_attribute(node, name)
38
+ end
39
+
40
+ xml.xpath("//*[@#{name}:*]").each do |node|
41
+ remove_matching_attribute(node, name)
42
+ end
40
43
  end
41
44
 
42
- def remove_namespaced_attributes
43
- namespaces_to_be_removed.each do |ns|
44
- xml.xpath("//*[@#{ns}:*]").each do |node|
45
- node.attributes.each do |_, attr|
46
- next unless attr.namespace
47
- attr.remove if attr.namespace.prefix == ns
48
- end
49
- end
45
+ def remove_namespace(namespace)
46
+ source = xml.root.to_s.gsub(/ *xmlns:#{namespace.prefix}=".*?"/, "")
47
+ xml.root = Nokogiri::XML(source).root
48
+ end
49
+
50
+ def remove_matching_attribute(node, name)
51
+ node.attributes.each do |_, attr|
52
+ next unless attr.namespace
53
+
54
+ attr.remove if attr.namespace.prefix == name
50
55
  end
51
56
  end
52
57
  end
@@ -11,9 +11,7 @@ module SvgOptimizer
11
11
  end
12
12
  end
13
13
 
14
- private
15
-
16
- def remove_if_empty(node, attr)
14
+ private def remove_if_empty(node, attr)
17
15
  node.remove_attribute(attr) if node[attr].empty?
18
16
  end
19
17
  end
@@ -3,7 +3,17 @@
3
3
  module SvgOptimizer
4
4
  module Plugins
5
5
  class RemoveEmptyContainer < Base
6
- ELEMENTS = %w[a defs g marker mask missing-glyph pattern switch symbol].freeze
6
+ ELEMENTS = %w[
7
+ a
8
+ defs
9
+ g
10
+ marker
11
+ mask
12
+ missing-glyph
13
+ pattern
14
+ switch
15
+ symbol
16
+ ].freeze
7
17
  SELECTOR = ELEMENTS.map {|element| %[#{element}:empty] }.join(", ")
8
18
 
9
19
  def process
@@ -12,9 +22,7 @@ module SvgOptimizer
12
22
  end
13
23
  end
14
24
 
15
- private
16
-
17
- def remove_node(node)
25
+ private def remove_node(node)
18
26
  node.children.empty? && node.remove
19
27
  remove_node(node.parent) if node.parent
20
28
  end
@@ -7,9 +7,7 @@ module SvgOptimizer
7
7
  xml.xpath("//text()").each(&method(:remove_if_empty))
8
8
  end
9
9
 
10
- private
11
-
12
- def remove_if_empty(node)
10
+ private def remove_if_empty(node)
13
11
  node.remove if node.text.gsub(/\s/, "").empty?
14
12
  end
15
13
  end
@@ -4,7 +4,7 @@ module SvgOptimizer
4
4
  module Plugins
5
5
  class RemoveTitle < Base
6
6
  def process
7
- xml.xpath("//title").remove
7
+ xml.css("title").remove
8
8
  end
9
9
  end
10
10
  end
@@ -13,6 +13,7 @@ module SvgOptimizer
13
13
 
14
14
  def remove_unused_ns(ns)
15
15
  return if xml.xpath("//#{ns.prefix}:*").any?
16
+ return if xml.xpath("//@*[namespace-uri()='#{ns.href}']").any?
16
17
 
17
18
  source = xml.root.to_s.gsub(/ *xmlns:#{ns.prefix}=".*?"/, "")
18
19
  xml.root = Nokogiri::XML(source).root
@@ -4,7 +4,12 @@ module SvgOptimizer
4
4
  module Plugins
5
5
  class RemoveUselessStrokeAndFill < Base
6
6
  SELECTOR = %w[circle ellipse line path polygon polyline rect].join(",")
7
- STROKE_ATTRS = %w[stroke stroke-opacity stroke-width stroke-dashoffset].freeze
7
+ STROKE_ATTRS = %w[
8
+ stroke
9
+ stroke-opacity
10
+ stroke-width
11
+ stroke-dashoffset
12
+ ].freeze
8
13
  FILL_ATTRS = %w[fill-opacity fill-rule].freeze
9
14
 
10
15
  def process
@@ -15,40 +20,39 @@ module SvgOptimizer
15
20
  end
16
21
  end
17
22
 
18
- private
19
-
20
- def remove_useless_attributes(node)
23
+ private def remove_useless_attributes(node)
21
24
  return if inherited_attribute(node, "id")
25
+
22
26
  remove_stroke(node) if remove_stroke?(node)
23
27
  remove_fill(node) if remove_fill?(node)
24
28
  end
25
29
 
26
- def remove_stroke(node)
30
+ private def remove_stroke(node)
27
31
  STROKE_ATTRS.each {|attr| node.delete(attr) }
28
32
  node["stroke"] = "none" if decline_inherited_stroke?(node)
29
33
  end
30
34
 
31
- def remove_fill(node)
35
+ private def remove_fill(node)
32
36
  FILL_ATTRS.each {|attr| node.delete(attr) }
33
37
  node["fill"] = "none" if decline_inherited_fill?(node)
34
38
  end
35
39
 
36
- def decline_inherited_stroke?(node)
40
+ private def decline_inherited_stroke?(node)
37
41
  (inherited_attribute(node.parent, "stroke") || "none") != "none"
38
42
  end
39
43
 
40
- def decline_inherited_fill?(node)
44
+ private def decline_inherited_fill?(node)
41
45
  !inherited_attribute(node, "fill") || node.has_attribute?("fill")
42
46
  end
43
47
 
44
- def remove_stroke?(node)
48
+ private def remove_stroke?(node)
45
49
  return true if (inherited_attribute(node, "stroke") || "none") == "none"
46
50
  return true if inherited_attribute(node, "stroke-opacity") == "0"
47
51
 
48
52
  inherited_attribute(node, "stroke-width") == "0"
49
53
  end
50
54
 
51
- def remove_fill?(node)
55
+ private def remove_fill?(node)
52
56
  fill = inherited_attribute(node, "fill")
53
57
 
54
58
  return true if fill == "none"
@@ -57,7 +61,7 @@ module SvgOptimizer
57
61
  !fill
58
62
  end
59
63
 
60
- def inherited_attribute(node, attr)
64
+ private def inherited_attribute(node, attr)
61
65
  return if node.nil? || node.document?
62
66
  return node[attr] if node.has_attribute?(attr)
63
67
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SvgOptimizer
4
- VERSION = "0.2.2".freeze
4
+ VERSION = "0.2.6"
5
5
  end
data/lib/svg_optimizer.rb CHANGED
@@ -6,7 +6,6 @@ require "svg_optimizer/version"
6
6
  require "svg_optimizer/plugins/base"
7
7
  require "svg_optimizer/plugins/cleanup_attribute"
8
8
  require "svg_optimizer/plugins/cleanup_id"
9
- require "svg_optimizer/plugins/collapse_groups"
10
9
  require "svg_optimizer/plugins/remove_comment"
11
10
  require "svg_optimizer/plugins/remove_metadata"
12
11
  require "svg_optimizer/plugins/remove_empty_text_node"
@@ -22,26 +21,29 @@ require "svg_optimizer/plugins/remove_description"
22
21
 
23
22
  module SvgOptimizer
24
23
  DEFAULT_PLUGINS = %w[
24
+ RemoveTitle
25
+ RemoveDescription
26
+ RemoveUnusedNamespace
25
27
  CleanupAttribute
26
28
  CleanupId
27
29
  RemoveComment
28
30
  RemoveMetadata
29
31
  RemoveEditorNamespace
30
32
  RemoveHiddenElement
31
- RemoveUnusedNamespace
32
33
  RemoveRasterImage
33
34
  RemoveEmptyAttribute
34
- CollapseGroups
35
35
  RemoveUselessStrokeAndFill
36
36
  RemoveEmptyTextNode
37
37
  RemoveEmptyContainer
38
- RemoveTitle
39
- RemoveDescription
40
38
  ].map {|name| Plugins.const_get(name) }
41
39
 
42
40
  def self.optimize(contents, plugins = DEFAULT_PLUGINS)
43
- xml = Nokogiri::XML(contents)
41
+ xml = Nokogiri::XML(contents) do |config|
42
+ config.recover.noent
43
+ end
44
+
44
45
  plugins.each {|plugin| plugin.new(xml).process }
46
+
45
47
  xml.root.to_xml
46
48
  end
47
49
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svg_optimizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-01 00:00:00.000000000 Z
11
+ date: 2022-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rake
42
+ name: minitest-utils
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -67,7 +67,35 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: minitest-utils
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-fnando
71
99
  requirement: !ruby/object:Gem::Requirement
72
100
  requirements:
73
101
  - - ">="
@@ -101,13 +129,12 @@ executables: []
101
129
  extensions: []
102
130
  extra_rdoc_files: []
103
131
  files:
104
- - LICENSE.txt
132
+ - LICENSE.md
105
133
  - README.md
106
134
  - lib/svg_optimizer.rb
107
135
  - lib/svg_optimizer/plugins/base.rb
108
136
  - lib/svg_optimizer/plugins/cleanup_attribute.rb
109
137
  - lib/svg_optimizer/plugins/cleanup_id.rb
110
- - lib/svg_optimizer/plugins/collapse_groups.rb
111
138
  - lib/svg_optimizer/plugins/remove_comment.rb
112
139
  - lib/svg_optimizer/plugins/remove_description.rb
113
140
  - lib/svg_optimizer/plugins/remove_editor_namespace.rb
@@ -124,8 +151,9 @@ files:
124
151
  homepage: https://github.com/fnando/svg_optimizer
125
152
  licenses:
126
153
  - MIT
127
- metadata: {}
128
- post_install_message:
154
+ metadata:
155
+ rubygems_mfa_required: 'true'
156
+ post_install_message:
129
157
  rdoc_options: []
130
158
  require_paths:
131
159
  - lib
@@ -133,16 +161,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
133
161
  requirements:
134
162
  - - ">="
135
163
  - !ruby/object:Gem::Version
136
- version: '0'
164
+ version: '2.7'
137
165
  required_rubygems_version: !ruby/object:Gem::Requirement
138
166
  requirements:
139
167
  - - ">="
140
168
  - !ruby/object:Gem::Version
141
169
  version: '0'
142
170
  requirements: []
143
- rubyforge_project:
144
- rubygems_version: 2.6.13
145
- signing_key:
171
+ rubygems_version: 3.3.3
172
+ signing_key:
146
173
  specification_version: 4
147
174
  summary: SVG optimization based on Node's SVGO
148
175
  test_files: []
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SvgOptimizer
4
- module Plugins
5
- class CollapseGroups < Base
6
- COLLAPSABLE_ATTRS = %w[transform class].freeze
7
-
8
- def process
9
- xml.css("g:not(:empty)").each do |group|
10
- collapse(group)
11
- end
12
- end
13
-
14
- private
15
-
16
- def collapse(group)
17
- collapse_attributes(group)
18
- group.swap(group.children) if collapse?(group)
19
- end
20
-
21
- def collapse_attributes(group)
22
- child = group.first_element_child
23
- return unless collapse_attributes?(group, child)
24
-
25
- group.attributes.each do |attr, val|
26
- if COLLAPSABLE_ATTRS.include?(attr)
27
- child[attr] = [val, child[attr]].compact.join(" ")
28
- else
29
- child[attr] ||= val
30
- end
31
-
32
- group.delete(attr)
33
- end
34
- end
35
-
36
- def collapse?(group)
37
- group.attributes.empty? &&
38
- !group.element_children.map(&:name).include?("animate")
39
- end
40
-
41
- def collapse_attributes?(group, child)
42
- return unless group.attributes.any?
43
- return unless group.element_children.length == 1
44
- return if child.has_attribute?("id")
45
- return unless !group.has_attribute?("clip-path") ||
46
- child.name == "g" &&
47
- !group.has_attribute?("transform") &&
48
- !child.has_attribute?("transform")
49
- true
50
- end
51
- end
52
- end
53
- end