svg_optimizer 0.0.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +39 -0
  4. data/lib/svg_optimizer/plugins/base.rb +11 -0
  5. data/lib/svg_optimizer/plugins/cleanup_attribute.rb +17 -0
  6. data/lib/svg_optimizer/plugins/cleanup_id.rb +70 -0
  7. data/lib/svg_optimizer/plugins/remove_comment.rb +9 -0
  8. data/lib/svg_optimizer/plugins/remove_editor_namespace.rb +32 -0
  9. data/lib/svg_optimizer/plugins/remove_empty_attribute.rb +18 -0
  10. data/lib/svg_optimizer/plugins/remove_empty_container.rb +20 -0
  11. data/lib/svg_optimizer/plugins/remove_empty_text_node.rb +14 -0
  12. data/lib/svg_optimizer/plugins/remove_hidden_element.rb +29 -0
  13. data/lib/svg_optimizer/plugins/remove_metadata.rb +9 -0
  14. data/lib/svg_optimizer/plugins/remove_raster_image.rb +16 -0
  15. data/lib/svg_optimizer/plugins/remove_unused_namespace.rb +17 -0
  16. data/lib/svg_optimizer/version.rb +3 -0
  17. data/lib/svg_optimizer.rb +47 -0
  18. data/spec/fixtures/cleanup_id.svg +18 -0
  19. data/spec/fixtures/cleanup_id_expected.svg +18 -0
  20. data/spec/fixtures/green.svg +37 -0
  21. data/spec/fixtures/unused_namespace.svg +13 -0
  22. data/spec/spec_helper.rb +30 -0
  23. data/spec/svg_optimizer/plugins/cleanup_attribute_spec.rb +6 -0
  24. data/spec/svg_optimizer/plugins/cleanup_id_spec.rb +12 -0
  25. data/spec/svg_optimizer/plugins/remove_comment_spec.rb +11 -0
  26. data/spec/svg_optimizer/plugins/remove_editor_namespace_spec.rb +8 -0
  27. data/spec/svg_optimizer/plugins/remove_empty_attribute_spec.rb +11 -0
  28. data/spec/svg_optimizer/plugins/remove_empty_container_spec.rb +8 -0
  29. data/spec/svg_optimizer/plugins/remove_empty_text_node_spec.rb +13 -0
  30. data/spec/svg_optimizer/plugins/remove_hidden_element_spec.rb +81 -0
  31. data/spec/svg_optimizer/plugins/remove_metadata_spec.rb +11 -0
  32. data/spec/svg_optimizer/plugins/remove_raster_image_spec.rb +14 -0
  33. data/spec/svg_optimizer/plugins/remove_unused_namespace_spec.rb +18 -0
  34. metadata +162 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 89a8f5445798684e296db58b8edae20833855329
4
+ data.tar.gz: 2051a95fee708a216349a60222789fbfc6f152e2
5
+ SHA512:
6
+ metadata.gz: 86a2e4a9d51bebd7ea0d43aa03382a7ac977080bb0e71a9c8a192ab396d7237355d902089a7c46e09438f8f8eabe8d48d13c43724af30130ae22256a00b15e29
7
+ data.tar.gz: ea12fa839b35f17cb69cbc4d0e2acb7985344010866d4d2ded4d3feffc1e654ade5319081ad18d487f6e40bb2a55f381818d662d293817fcced05c33781f0e8c
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Nando Vieira
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # SvgOptimizer
2
+
3
+ Some small optimizations for SVG files.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'svg_optimizer'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install svg_optimizer
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ # Optimize an existing String.
23
+ xml = File.read("file.svg")
24
+ optimized = SvgOptimizer.optimize(xml)
25
+
26
+ # Optimize a file - it will override the original file.
27
+ SvgOptimizer.optimize_file("file.svg")
28
+
29
+ # Optimize a file - it saves a copy to "optimized/file.svg".
30
+ SvgOptimizer.optimize_file("file.svg", "optimized/file.svg")
31
+ ```
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create new Pull Request
@@ -0,0 +1,11 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class Base
4
+ attr_reader :xml
5
+
6
+ def initialize(xml)
7
+ @xml = xml
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class CleanupAttribute < Base
4
+ def process
5
+ xml.xpath("//*[@*]").each do |node|
6
+ node.attributes.each do |_, attribute|
7
+ cleanup_attribute attribute
8
+ end
9
+ end
10
+ end
11
+
12
+ def cleanup_attribute(attribute)
13
+ attribute.value = attribute.value.strip.squeeze(" ")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,70 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class CleanupId < Base
4
+ LETTERS = %w[
5
+ a b c d e f g h i j k l m n o p q r s t u v w x y z
6
+ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
7
+ ]
8
+
9
+ IDS = LETTERS.concat(LETTERS.combination(2).to_a)
10
+
11
+ def ids
12
+ @ids ||= IDS.dup
13
+ end
14
+
15
+ def process
16
+ # If there a <script> or <style>, don't mess with ids.
17
+ return if xml.css("script, style").any?
18
+
19
+ # Replace the ids otherwise.
20
+ xml.css("[id]").each(&method(:cleanup_id))
21
+ end
22
+
23
+ def cleanup_id(node)
24
+ # Keep ids if there's no available id.
25
+ # This means that 1300+ ids have been used so far. CRAZY!
26
+ return if ids.empty?
27
+
28
+ old_id = node[:id]
29
+ new_id = ids.shift
30
+ node[:id] = new_id
31
+
32
+ remove_unused_id(
33
+ node,
34
+ replace_url_references(old_id, new_id),
35
+ replace_href_references(old_id, new_id)
36
+ )
37
+ end
38
+
39
+ def remove_unused_id(node, has_url_refs, has_href_refs)
40
+ return if has_url_refs
41
+ return if has_href_refs
42
+ node.remove_attribute("id")
43
+ end
44
+
45
+ def replace_url_references(old_id, new_id)
46
+ nodes = xml.xpath(%{//*[@*="url(##{old_id})"]})
47
+
48
+ nodes.each do |node|
49
+ node.attributes.map(&:last).each do |attr|
50
+ attr.value = %[url(##{new_id})] if attr.value == %[url(##{old_id})]
51
+ end
52
+ end
53
+
54
+ nodes.any?
55
+ end
56
+
57
+ def replace_href_references(old_id, new_id)
58
+ nodes = xml.css("[href='##{old_id}'], [xlink|href='##{old_id}']")
59
+
60
+ nodes.each do |node|
61
+ node.attributes.map(&:last).each do |attr|
62
+ attr.value = "##{new_id}" if attr.value == "##{old_id}"
63
+ end
64
+ end
65
+
66
+ nodes.any?
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,9 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class RemoveComment < Base
4
+ def process
5
+ xml.xpath("//comment()").remove
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class RemoveEditorNamespace < Base
4
+ NAMESPACES = %w[
5
+ http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd
6
+ http://www.inkscape.org/namespaces/inkscape
7
+ http://ns.adobe.com/AdobeIllustrator/10.0/
8
+ http://ns.adobe.com/Graphs/1.0/
9
+ http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/
10
+ http://ns.adobe.com/Variables/1.0/
11
+ http://ns.adobe.com/SaveForWeb/1.0/
12
+ http://ns.adobe.com/Extensibility/1.0/
13
+ http://ns.adobe.com/Flows/1.0/
14
+ http://ns.adobe.com/ImageReplacement/1.0/
15
+ http://ns.adobe.com/GenericCustomNamespace/1.0/
16
+ http://ns.adobe.com/XPath/1.0
17
+ ]
18
+
19
+ def process
20
+ namespaces = xml.namespaces
21
+ xml.remove_namespaces!
22
+
23
+ namespaces.each do |name, value|
24
+ next if NAMESPACES.include?(value)
25
+
26
+ _, name = name.split(":")
27
+ xml.root.add_namespace name, value
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,18 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class RemoveEmptyAttribute < Base
4
+ def process
5
+ xml.xpath("//*[@*='']").each do |node|
6
+ node.attributes.each do |name, value|
7
+ remove_if_empty node, name
8
+ end
9
+ end
10
+ end
11
+
12
+ private
13
+ def remove_if_empty(node, attr)
14
+ node.remove_attribute(attr) if node[attr].empty?
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class RemoveEmptyContainer < Base
4
+ ELEMENTS = %w[a defs g marker mask missing-glyph pattern switch symbol]
5
+ SELECTOR = ELEMENTS.map {|element| %[#{element}:empty] }.join(", ")
6
+
7
+ def process
8
+ while (nodes = xml.css(SELECTOR)).any?
9
+ nodes.each(&method(:remove_node))
10
+ end
11
+ end
12
+
13
+ private
14
+ def remove_node(node)
15
+ node.children.empty? && node.remove
16
+ remove_node(node.parent) if node.parent
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class RemoveEmptyTextNode < Base
4
+ def process
5
+ xml.xpath("//text()").each(&method(:remove_if_empty))
6
+ end
7
+
8
+ private
9
+ def remove_if_empty(node)
10
+ node.remove if node.text.gsub(/\s/, "").empty?
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class RemoveHiddenElement < Base
4
+ SELECTOR = %w[
5
+ [display=none]
6
+ [opacity='0']
7
+ circle[r='0']
8
+ ellipse[rx='0']
9
+ ellipse[ry='0']
10
+ rect[width='0']
11
+ rect[height='0']
12
+ pattern[width='0']
13
+ pattern[height='0']
14
+ image[width='0']
15
+ image[height='0']
16
+ path[d='']
17
+ path:not([d])
18
+ polyline[points='']
19
+ polyline:not([points])
20
+ polygon[points='']
21
+ polygon:not([points])
22
+ ].join(", ")
23
+
24
+ def process
25
+ xml.css(SELECTOR).remove
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class RemoveMetadata < Base
4
+ def process
5
+ xml.css("metadata").remove
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class RemoveRasterImage < Base
4
+ SELECTOR = %w[
5
+ image[xlink|href$='.jpg']
6
+ image[xlink|href$='.jpeg']
7
+ image[xlink|href$='.gif']
8
+ image[xlink|href$='.png']
9
+ ].join(", ")
10
+
11
+ def process
12
+ xml.css(SELECTOR).remove
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module SvgOptimizer
2
+ module Plugins
3
+ class RemoveUnusedNamespace < Base
4
+ def process
5
+ xml.root.namespace_definitions
6
+ .select(&:prefix)
7
+ .each(&method(:remove_unused_ns))
8
+ end
9
+
10
+ def remove_unused_ns(ns)
11
+ return if xml.xpath("//#{ns.prefix}:*").any?
12
+ source = xml.root.to_s.gsub(/ *xmlns:#{ns.prefix}=".*?"/, "")
13
+ xml.root = Nokogiri::XML(source).root
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module SvgOptimizer
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,47 @@
1
+ require "nokogiri"
2
+
3
+ require "svg_optimizer/version"
4
+ require "svg_optimizer/plugins/base"
5
+ require "svg_optimizer/plugins/cleanup_attribute"
6
+ require "svg_optimizer/plugins/cleanup_id"
7
+ require "svg_optimizer/plugins/remove_comment"
8
+ require "svg_optimizer/plugins/remove_metadata"
9
+ require "svg_optimizer/plugins/remove_empty_text_node"
10
+ require "svg_optimizer/plugins/remove_empty_container"
11
+ require "svg_optimizer/plugins/remove_editor_namespace"
12
+ require "svg_optimizer/plugins/remove_hidden_element"
13
+ require "svg_optimizer/plugins/remove_raster_image"
14
+ require "svg_optimizer/plugins/remove_empty_attribute"
15
+ require "svg_optimizer/plugins/remove_unused_namespace"
16
+
17
+ module SvgOptimizer
18
+ PLUGINS = %w[
19
+ CleanupAttribute
20
+ CleanupId
21
+ RemoveComment
22
+ RemoveMetadata
23
+ RemoveEditorNamespace
24
+ RemoveHiddenElement
25
+ RemoveUnusedNamespace
26
+ RemoveRasterImage
27
+ RemoveEmptyAttribute
28
+ RemoveEmptyTextNode
29
+ RemoveEmptyContainer
30
+ ]
31
+
32
+ def self.optimize(contents)
33
+ xml = Nokogiri::XML(contents)
34
+ PLUGINS.each do |plugin_name|
35
+ Plugins.const_get(plugin_name).new(xml).process
36
+ end
37
+
38
+ xml.root.to_xml
39
+ end
40
+
41
+ def self.optimize_file(path, target = path)
42
+ contents = optimize(File.read(path))
43
+
44
+ File.open(target, "w") {|file| file << contents }
45
+ true
46
+ end
47
+ end
@@ -0,0 +1,18 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
2
+ <defs>
3
+ <linearGradient id="gradient001">
4
+ <stop offset="5%" stop-color="#F60"/>
5
+ <stop offset="95%" stop-color="#FF6"/>
6
+ </linearGradient>
7
+ <text id="referencedText">
8
+ referenced text
9
+ </text>
10
+ </defs>
11
+ <g id="g001">
12
+ <circle id="circle001" fill="url(#gradient001)" cx="60" cy="60" r="50"/>
13
+ <tref xlink:href="#referencedText"/>
14
+ </g>
15
+ <g>
16
+ <tref xlink:href="#referencedText"/>
17
+ </g>
18
+ </svg>
@@ -0,0 +1,18 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
2
+ <defs>
3
+ <linearGradient id="a">
4
+ <stop offset="5%" stop-color="#F60"/>
5
+ <stop offset="95%" stop-color="#FF6"/>
6
+ </linearGradient>
7
+ <text id="b">
8
+ referenced text
9
+ </text>
10
+ </defs>
11
+ <g>
12
+ <circle fill="url(#a)" cx="60" cy="60" r="50"/>
13
+ <tref xlink:href="#b"/>
14
+ </g>
15
+ <g>
16
+ <tref xlink:href="#b"/>
17
+ </g>
18
+ </svg>
@@ -0,0 +1,37 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5
+ width="10px" height="10px" viewBox="0 0 10 10" enable-background="new 0 0 10 10" xml:space="preserve">
6
+ <rect fill="#39B54A" width="10" height="10"/>
7
+ <g>
8
+ </g>
9
+ <g>
10
+ </g>
11
+ <g>
12
+ </g>
13
+ <g>
14
+ </g>
15
+ <g>
16
+ </g>
17
+ <g>
18
+ </g>
19
+ <g>
20
+ </g>
21
+ <g>
22
+ </g>
23
+ <g>
24
+ </g>
25
+ <g>
26
+ </g>
27
+ <g>
28
+ </g>
29
+ <g>
30
+ </g>
31
+ <g>
32
+ </g>
33
+ <g>
34
+ </g>
35
+ <g>
36
+ </g>
37
+ </svg>
@@ -0,0 +1,13 @@
1
+ <svg
2
+ xmlns="http://www.w3.org/2000/svg"
3
+ xmlns:test="http://example.com/"
4
+ xmlns:test2="http://example2.com/"
5
+ xmlns:test3="http://example3.com/"
6
+ xmlns:test4="http://example4.com/"
7
+ >
8
+ <test:elem>
9
+ <test2:elem>
10
+ test
11
+ </test2:elem>
12
+ </test:elem>
13
+ </svg>
@@ -0,0 +1,30 @@
1
+ require "bundler/setup"
2
+ require "svg_optimizer"
3
+
4
+ module RSpecHelpers
5
+ SVG = <<-XML
6
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
7
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
8
+ <?xml version="1.0" encoding="utf-8"?>
9
+ <svg xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
10
+ %s
11
+ </svg>
12
+ XML
13
+
14
+ def with_svg_plugin(content)
15
+ let(:file_path) { File.expand_path("../fixtures/#{content}", __FILE__) }
16
+ let(:input_xml) { Nokogiri::XML(File.file?(file_path) ? File.read(file_path) : SVG % content) }
17
+ let(:plugin) { described_class.new(input_xml) }
18
+ let(:xml) { plugin.xml }
19
+ before { plugin.process }
20
+ end
21
+ end
22
+
23
+
24
+ RSpec.configure do |config|
25
+ config.treat_symbols_as_metadata_keys_with_true_values = true
26
+ config.run_all_when_everything_filtered = true
27
+ config.filter_run :focus
28
+ config.order = "random"
29
+ config.extend RSpecHelpers
30
+ end
@@ -0,0 +1,6 @@
1
+ require "spec_helper"
2
+
3
+ describe SvgOptimizer::Plugins::CleanupAttribute do
4
+ with_svg_plugin %[<g a="b \n\t\tc"/>]
5
+ it { expect(xml.css("g").first["a"]).to eql("b c") }
6
+ end
@@ -0,0 +1,12 @@
1
+ require "spec_helper"
2
+
3
+ describe SvgOptimizer::Plugins::CleanupId do
4
+ with_svg_plugin "cleanup_id.svg"
5
+
6
+ it { expect(xml.css("linearGradient").first["id"]).to eql("a") }
7
+ it { expect(xml.css("circle").first["fill"]).to eql("url(#a)") }
8
+ it { expect(xml.css("circle[id]")).to be_empty }
9
+ it { expect(xml.css("g[id]")).to be_empty }
10
+ it { expect(xml.css("tref[xlink|href='#b']").size).to eql(2) }
11
+ it { expect(xml.css("text").first["id"]).to eql("b") }
12
+ end
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ describe SvgOptimizer::Plugins::RemoveComment do
4
+ with_svg_plugin <<-SVG
5
+ <!-- foo -->
6
+ <g></g>
7
+ <!-- bar -->
8
+ SVG
9
+
10
+ it { expect(xml.xpath("//comment()")).to be_empty }
11
+ end
@@ -0,0 +1,8 @@
1
+ require "spec_helper"
2
+
3
+ describe SvgOptimizer::Plugins::RemoveEditorNamespace do
4
+ with_svg_plugin ""
5
+ it { expect(xml.namespaces.values).not_to include("http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd") }
6
+ it { expect(xml.namespaces.values).to include("http://www.w3.org/2000/svg") }
7
+ it { expect(xml.namespaces.values).to include("http://www.w3.org/1999/xlink") }
8
+ end
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ describe SvgOptimizer::Plugins::RemoveEmptyAttribute do
4
+ with_svg_plugin <<-SVG
5
+ <g attr1="" attr2=""/>
6
+ <g attr3="" attr4=""/>
7
+ <g namespace:attr="" />
8
+ SVG
9
+
10
+ it { expect(xml.xpath("//*[@*='']")).to be_empty }
11
+ end
@@ -0,0 +1,8 @@
1
+ require "spec_helper"
2
+
3
+ describe SvgOptimizer::Plugins::RemoveEmptyContainer do
4
+ context "inner elements" do
5
+ with_svg_plugin "<g><marker><a/></marker></g>"
6
+ it { expect(xml.root.css("*")).to be_empty }
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ describe SvgOptimizer::Plugins::RemoveEmptyTextNode do
4
+ context "groups with empty text nodes only" do
5
+ with_svg_plugin %[<g> \n\t\r\n </g>]
6
+ it { expect(xml.css("g").children).to be_empty }
7
+ end
8
+
9
+ context "groups with non-empty nodes" do
10
+ with_svg_plugin %[<g> Hello \n\t\r\n </g>]
11
+ it { expect(xml.css("g").children).not_to be_empty }
12
+ end
13
+ end
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+
3
+ describe SvgOptimizer::Plugins::RemoveHiddenElement do
4
+ context "display: none" do
5
+ with_svg_plugin <<-SVG
6
+ <path display="none" d="..."/>
7
+ SVG
8
+
9
+ it { expect(xml.css("path")).to be_empty }
10
+ end
11
+
12
+ context "opacity: 0" do
13
+ with_svg_plugin <<-SVG
14
+ <path opacity="0" d="..."/>
15
+ SVG
16
+
17
+ it { expect(xml.css("path")).to be_empty }
18
+ end
19
+
20
+ context "circle" do
21
+ with_svg_plugin <<-SVG
22
+ <circle r="0"/>
23
+ SVG
24
+
25
+ it { expect(xml.css("circle")).to be_empty }
26
+ end
27
+
28
+ context "ellipse" do
29
+ with_svg_plugin <<-SVG
30
+ <ellipse rx="0"/>
31
+ <ellipse ry="0"/>
32
+ SVG
33
+
34
+ it { expect(xml.css("ellipse")).to be_empty }
35
+ end
36
+
37
+ context "rect" do
38
+ with_svg_plugin <<-SVG
39
+ <rect width="0"/>
40
+ <rect height="0"/>
41
+ SVG
42
+
43
+ it { expect(xml.css("rect")).to be_empty }
44
+ end
45
+
46
+ context "pattern" do
47
+ with_svg_plugin <<-SVG
48
+ <pattern width="0"/>
49
+ <pattern height="0"/>
50
+ SVG
51
+
52
+ it { expect(xml.css("pattern")).to be_empty }
53
+ end
54
+
55
+ context "image" do
56
+ with_svg_plugin <<-SVG
57
+ <image width="0"/>
58
+ <image height="0"/>
59
+ SVG
60
+
61
+ it { expect(xml.css("image")).to be_empty }
62
+ end
63
+
64
+ context "<path d=''/>" do
65
+ with_svg_plugin <<-SVG
66
+ <path d=''/>
67
+ SVG
68
+
69
+ it { expect(xml.css("path")).to be_empty }
70
+ end
71
+
72
+ context "other hidden elements" do
73
+ with_svg_plugin <<-SVG
74
+ <path/>
75
+ <polyline/>
76
+ <polygon/>
77
+ SVG
78
+
79
+ it { expect(xml.root.css("*")).to be_empty }
80
+ end
81
+ end
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ describe SvgOptimizer::Plugins::RemoveMetadata do
4
+ with_svg_plugin <<-SVG
5
+ <metadata></metadata>
6
+ <!-- foo -->
7
+ <metadata></metadata>
8
+ SVG
9
+
10
+ it { expect(xml.css("metadata")).to be_empty }
11
+ end
@@ -0,0 +1,14 @@
1
+ require "spec_helper"
2
+
3
+ describe SvgOptimizer::Plugins::RemoveRasterImage do
4
+ with_svg_plugin <<-SVG
5
+ <g>
6
+ <image xlink:href="raster.jpg" width="100" height="100"/>
7
+ <image xlink:href="raster.png" width="100" height="100"/>
8
+ <image xlink:href="raster.gif" width="100" height="100"/>
9
+ <image xlink:href="raster.svg" width="100" height="100"/>
10
+ </g>
11
+ SVG
12
+
13
+ it { expect(xml.css("image").size).to eql(1) }
14
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe SvgOptimizer::Plugins::RemoveUnusedNamespace do
4
+ with_svg_plugin "unused_namespace.svg"
5
+
6
+ let(:namespaces) do
7
+ xml.root.namespace_definitions.each_with_object({}) do |ns, buffer|
8
+ next unless ns.prefix
9
+ buffer[ns.prefix] = ns.href
10
+ end
11
+ end
12
+
13
+ it { expect(namespaces).to include("test" => "http://example.com/") }
14
+ it { expect(namespaces).to include("test2" => "http://example2.com/") }
15
+
16
+ it { expect(namespaces).not_to include("test3" => "http://example3.com/") }
17
+ it { expect(namespaces).not_to include("test4" => "http://example4.com/") }
18
+ end
metadata ADDED
@@ -0,0 +1,162 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: svg_optimizer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Nando Vieira
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-meta
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
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
+ description: SVG optimization based on Node's SVGO
84
+ email:
85
+ - fnando.vieira@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - LICENSE.txt
91
+ - README.md
92
+ - lib/svg_optimizer/plugins/base.rb
93
+ - lib/svg_optimizer/plugins/cleanup_attribute.rb
94
+ - lib/svg_optimizer/plugins/cleanup_id.rb
95
+ - lib/svg_optimizer/plugins/remove_comment.rb
96
+ - lib/svg_optimizer/plugins/remove_editor_namespace.rb
97
+ - lib/svg_optimizer/plugins/remove_empty_attribute.rb
98
+ - lib/svg_optimizer/plugins/remove_empty_container.rb
99
+ - lib/svg_optimizer/plugins/remove_empty_text_node.rb
100
+ - lib/svg_optimizer/plugins/remove_hidden_element.rb
101
+ - lib/svg_optimizer/plugins/remove_metadata.rb
102
+ - lib/svg_optimizer/plugins/remove_raster_image.rb
103
+ - lib/svg_optimizer/plugins/remove_unused_namespace.rb
104
+ - lib/svg_optimizer/version.rb
105
+ - lib/svg_optimizer.rb
106
+ - spec/fixtures/cleanup_id.svg
107
+ - spec/fixtures/cleanup_id_expected.svg
108
+ - spec/fixtures/green.svg
109
+ - spec/fixtures/unused_namespace.svg
110
+ - spec/spec_helper.rb
111
+ - spec/svg_optimizer/plugins/cleanup_attribute_spec.rb
112
+ - spec/svg_optimizer/plugins/cleanup_id_spec.rb
113
+ - spec/svg_optimizer/plugins/remove_comment_spec.rb
114
+ - spec/svg_optimizer/plugins/remove_editor_namespace_spec.rb
115
+ - spec/svg_optimizer/plugins/remove_empty_attribute_spec.rb
116
+ - spec/svg_optimizer/plugins/remove_empty_container_spec.rb
117
+ - spec/svg_optimizer/plugins/remove_empty_text_node_spec.rb
118
+ - spec/svg_optimizer/plugins/remove_hidden_element_spec.rb
119
+ - spec/svg_optimizer/plugins/remove_metadata_spec.rb
120
+ - spec/svg_optimizer/plugins/remove_raster_image_spec.rb
121
+ - spec/svg_optimizer/plugins/remove_unused_namespace_spec.rb
122
+ homepage: https://github.com/fnando/svg_optimizer
123
+ licenses:
124
+ - MIT
125
+ metadata: {}
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubyforge_project:
142
+ rubygems_version: 2.0.3
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: SVG optimization based on Node's SVGO
146
+ test_files:
147
+ - spec/fixtures/cleanup_id.svg
148
+ - spec/fixtures/cleanup_id_expected.svg
149
+ - spec/fixtures/green.svg
150
+ - spec/fixtures/unused_namespace.svg
151
+ - spec/spec_helper.rb
152
+ - spec/svg_optimizer/plugins/cleanup_attribute_spec.rb
153
+ - spec/svg_optimizer/plugins/cleanup_id_spec.rb
154
+ - spec/svg_optimizer/plugins/remove_comment_spec.rb
155
+ - spec/svg_optimizer/plugins/remove_editor_namespace_spec.rb
156
+ - spec/svg_optimizer/plugins/remove_empty_attribute_spec.rb
157
+ - spec/svg_optimizer/plugins/remove_empty_container_spec.rb
158
+ - spec/svg_optimizer/plugins/remove_empty_text_node_spec.rb
159
+ - spec/svg_optimizer/plugins/remove_hidden_element_spec.rb
160
+ - spec/svg_optimizer/plugins/remove_metadata_spec.rb
161
+ - spec/svg_optimizer/plugins/remove_raster_image_spec.rb
162
+ - spec/svg_optimizer/plugins/remove_unused_namespace_spec.rb