jekyll-inline-svg 0.0.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 54bf469b224e7c7af5dd5168fa7f417cde9aefe8
4
- data.tar.gz: 6419acd66b53406b7d62633a11fb6e439a5c9945
3
+ metadata.gz: 5f7ec02900a1781590f77c085955e691f67c2413
4
+ data.tar.gz: c85d53a5af01ba620036633997fbf3573143650d
5
5
  SHA512:
6
- metadata.gz: e4ef60f184b0179b254afa2cb641a87b52d51dae78c6a87123aa1e3be9b3aa276f69fd81dd340f524ab1491d73387475be1eaf2df49bbe821627cefb225ec71d
7
- data.tar.gz: 8692d77303fb7400b35705ced6a9bc1a7f654a976088777b6e6b544f5494542f6bb152be76e3dda94351e06edb60b467e8c5ed243e476840f29b36d452014c24
6
+ metadata.gz: e07e67d5aaf9eb24629a31dbaaa9b76e4224c8b6ef517967944fe1b784aff9180deb4d09d0542b9852d4a6f69104dda173d722e8b76628b051c0fac846a80f1d
7
+ data.tar.gz: 7c82653e38eaafd4f2dba396e8bc09fd06154318d14cc7609125d9cb9c077d564a051fb0ecbd5f8b6f6d89add676f942810b9bdd1c5e3dacf06d9a9043d5f984
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- jekyll-inline-svg (0.0.1)
4
+ jekyll-inline-svg (0.0.2)
5
5
  jekyll (~> 3.3)
6
6
  svg_optimizer (= 0.1.0)
7
7
 
data/README.md CHANGED
@@ -15,6 +15,13 @@ gems:
15
15
  - jekyll-inline-svg
16
16
  ```
17
17
 
18
+ Optimization is opt-in and can be enabled by adding this to your `_config.yml`
19
+
20
+ ```
21
+ svg:
22
+ optimize: true
23
+ ```
24
+
18
25
  ## Usage
19
26
 
20
27
  Use the Liquid tag in your pages :
@@ -48,6 +55,9 @@ Liquid variables will be interpreted if enclosed in double brackets :
48
55
  {% assign size=40 %}
49
56
  {% svg "/path/to/{{site.foo-name}}.svg" width="{{size}}" %}
50
57
  ```
58
+ `height` is automatically set to match `width` if omitted. It can't be left unset because IE11 won't use the viewport attribute to calculate the image's aspect ratio.
59
+
60
+
51
61
 
52
62
  Relative paths and absolute paths will both be interpreted from Jekyll's configured [source directory](https://jekyllrb.com/docs/configuration/). So both :
53
63
 
@@ -74,3 +84,10 @@ Some processing is done to remove useless data :
74
84
  If any important data gets removed, or the output SVG looks different from input, it's a bug. Please file an issue to this repository describing your problem.
75
85
 
76
86
  It does not perform any input validation on attributes. They will be appended as-is to the root node.
87
+
88
+ ## Motivations
89
+
90
+ This has been creeated specifically to display svg icons in html pages.
91
+
92
+ PNG/BMP sprites are clearly a no go in a world where "a screen" can be anything from 4" to 150", ranging from 480p to 4k. So what are our vector alternatives?
93
+ Font-icons are [bad](https://cloudfour.com/thinks/seriously-dont-use-icon-fonts/). While **xlink** looks like an ideal solution, with an elegant : `<use xlink:href="/path/to/icons.svg#play"></use>`, it's badly supported in IE (up to ie11). And embedding SVGs in an `<img>` is not going to cut it. Inlined SVG icons, in my opinion, is the best option we got right now. It's also where the industry seems to be going, with big actors like [github](https://github.com/blog/2112-delivering-octicons-with-svg) starting to transition from font-icons to inlined SVG.
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  A Liquid tag to inline and optimize SVG images in your HTML
8
8
  Supports custom DOM Attributes parameters and variables interpretation.
9
9
  EOF
10
- spec.version = "0.0.2"
10
+ spec.version = "1.0.0"
11
11
  spec.authors = ["Sebastien DUMETZ"]
12
12
  spec.email = "s.dumetz@holusion.com"
13
13
  spec.homepage = "https://github.com/sdumetz/jekyll-inline-svg"
@@ -1,21 +1,14 @@
1
+ require "nokogiri"
1
2
  require 'svg_optimizer'
2
3
  require 'jekyll/liquid_extensions'
3
- class RemoveSize < SvgOptimizer::Plugins::Base
4
- # remove "width" and "height" attributes
5
- def process
6
- xml.root.remove_attribute("height")
7
- xml.root.remove_attribute("width")
8
- end
9
- end
4
+
10
5
  PLUGINS_BLACKLIST = [
11
6
  SvgOptimizer::Plugins::CleanupId,
12
7
  ]
13
8
 
14
9
  PLUGINS = SvgOptimizer::DEFAULT_PLUGINS.delete_if {|plugin|
15
10
  PLUGINS_BLACKLIST.include? plugin
16
- }+[
17
- RemoveSize
18
- ]
11
+ }
19
12
 
20
13
 
21
14
  module Jekyll
@@ -33,10 +26,13 @@ module Jekyll
33
26
  ^(?<path>[^\s"']+|"[^"]*"|'[^']*')
34
27
  (?<params>.*)
35
28
  !x
29
+ PARAM_SYNTAX= %r!
30
+ ([\w-]+)\s*=\s*
31
+ (?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))
32
+ !x
36
33
 
37
34
  def initialize(tag_name, input, tokens)
38
35
  super
39
-
40
36
  @svg, @params = JekyllInlineSvg.parse_params(input)
41
37
  end
42
38
 
@@ -47,23 +43,68 @@ module Jekyll
47
43
  end
48
44
  markup
49
45
  end
50
-
46
+ def split_params(markup, context)
47
+ params={}
48
+ while (match = PARAM_SYNTAX.match(markup))
49
+ markup = markup[match.end(0)..-1]
50
+ value = if match[2]
51
+ interpolate(match[2].gsub(%r!\\"!, '"'), context)
52
+ elsif match[3]
53
+ interpolate(match[3].gsub(%r!\\'!, "'"),context)
54
+ elsif match[4]
55
+ lookup_variable(context, match[4])
56
+ end
57
+ params[match[1]] = value
58
+ end
59
+ return params
60
+ end
51
61
  #Parse parameters. Returns : [svg_path, parameters]
52
62
  # Does not interpret variables as it's done at render time
53
63
  def self.parse_params(input)
54
64
  matched = input.strip.match(PATH_SYNTAX)
55
- return matched["path"].gsub("\"","").gsub("'","").strip, matched["params"].strip
65
+ path = matched["path"].gsub("\"","").gsub("'","").strip
66
+ markup = matched["params"].strip
67
+ return path, markup
68
+ end
69
+ def fmt(params)
70
+ r = params.to_a.select{|v| v[1] != ""}.map {|v| %!#{v[0]}="#{v[1]}"!}
71
+ r.join(" ")
72
+ end
73
+ def create_plugin(params)
74
+ mod = Class.new(SvgOptimizer::Plugins::Base) do
75
+ def self.set (p)
76
+ @@params = p
77
+ end
78
+ def process
79
+ @@params.each {|key,val| xml.root.set_attribute(key,val)}
80
+ return xml
81
+ end
82
+ end
83
+ mod.set(params)
84
+ return mod
56
85
  end
57
86
  def render(context)
58
87
  #global site variable
59
88
  site = context.registers[:site]
60
89
  #check if given name is a variable. Otherwise use it as a file name
61
90
  svg_file = Jekyll.sanitized_path(site.source, interpolate(@svg,context))
62
- params = interpolate(@params,context)
63
-
64
- xml = File.open(svg_file, "rb")
65
- optimized = SvgOptimizer.optimize(xml.read, PLUGINS)
66
- "#{optimized.sub("<svg ","<svg #{params} ")}"
91
+ #replace variables with their current value
92
+ params = split_params(@params,context)
93
+ #because ie11 require to have a height AND a width
94
+ if params.key? "width" and ! params.key? "height"
95
+ params["height"] = params["width"]
96
+ end
97
+ #params = @params
98
+ file = File.open(svg_file, "rb").read
99
+ conf = lookup_variable(context,"site.svg")
100
+ if conf["optimize"] == true
101
+ xml = SvgOptimizer.optimize(file, [create_plugin(params)] + PLUGINS)
102
+ else
103
+ xml = Nokogiri::XML(file)
104
+ params.each {|key,val| xml.root.set_attribute(key,val)}
105
+ xml = xml.to_xml
106
+ end
107
+ return xml
67
108
  end
68
109
  end
69
110
  end
@@ -7,8 +7,3 @@ defaults:
7
7
  type: page
8
8
  values:
9
9
  layout: default
10
- -
11
- scope:
12
- path: "static_files/excluded.pdf"
13
- values:
14
- sitemap: false
@@ -2,4 +2,5 @@
2
2
  <?xml version="1.0" encoding="utf-8"?>
3
3
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 24 24" width="150" height="150">
4
4
  <rect width="20" height="20" x="2" y="2" />
5
+ <!-- comment -->
5
6
  </svg>
@@ -7,6 +7,12 @@ Hello world
7
7
  {% svg files/square.svg %}
8
8
  </div>
9
9
 
10
+ <div id="height">
11
+ {% svg files/square.svg width=24 %}
12
+ {% svg files/square.svg width=24 height=48 %}
13
+ {% svg files/square.svg width=24 height="" %}
14
+ </div>
15
+
10
16
  <div id="path">
11
17
  <label>Resolve relative and absolute paths to site's source</label>
12
18
  {% svg files/square.svg %}
@@ -24,3 +30,7 @@ Hello world
24
30
  {% svg /files/{{page.svgname}}.svg %}
25
31
  {% svg /files/square.svg id="name-{{page.svgname}}" class="class-{{page.svgclass}}" %}
26
32
  </div>
33
+
34
+ <div id="optimize">
35
+ {% svg /files/{{page.svgname}}.svg data-foo="" %}
36
+ </div>
@@ -45,50 +45,74 @@ describe(Jekyll::Tags::JekyllInlineSvg) do
45
45
  expect(params).to eq("id='bar' style=\"hello\"")
46
46
  end
47
47
  end
48
+ [
49
+ Jekyll.configuration({
50
+ "source" => source_dir,
51
+ "destination" => dest_dir,
52
+ "url" => "http://example.org",
53
+ }),
54
+ Jekyll.configuration({
55
+ "source" => source_dir,
56
+ "destination" => dest_dir,
57
+ "url" => "http://example.org",
58
+ "svg" => { "optimize" => true}
59
+ })
60
+ ].each do |config|
61
+ is_opt = config["svg"] and config["svg"]["optimize"] == true
62
+ describe "Integration (with #{is_opt ? "" : "no"} optimisation)" do
63
+ before(:context) do
64
+ site = Jekyll::Site.new(config)
65
+ site.process
66
+ @data = parse("index.html")
67
+ @base = @data.css("#base").css("svg").first
68
+ end
69
+ it "render site" do
70
+ expect(File.exist?(dest_dir("index.html"))).to be_truthy
71
+ end
72
+ it "exports svg" do
73
+ data = @data.xpath("//svg")
74
+ expect(data).to be_truthy
75
+ expect(data.first).to be_truthy
76
+ expect(@base).to be_truthy
77
+ # Do not strip other width and height attributes
78
+ end
79
+ it "add a height if only width is given" do
80
+ data = @data.css("#height").css("svg")
81
+ expect(data).to be_truthy
82
+ expect(data[0].get_attribute("height")).to eql("24")
83
+ expect(data[0].get_attribute("width")).to eql("24")
84
+ # do not set height if given
85
+ expect(data[1].get_attribute("height")).to eql("48")
86
+ expect(data[1].get_attribute("width")).to eql("24")
87
+ #do not set height if forced to empty string
88
+ expect(data[2].get_attribute("height")).to is_opt ? be_falsy : eql("")
48
89
 
49
- describe "Integration" do
50
-
51
- before(:context) do
52
- config = Jekyll.configuration({
53
- "source" => source_dir,
54
- "destination" => dest_dir,
55
- "url" => "http://example.org",
56
- })
57
- site = Jekyll::Site.new(config)
58
- site.process
59
- @data = parse("index.html")
60
- @base = @data.css("#base").css("svg").first
61
- end
62
- it "render site" do
63
- expect(File.exist?(dest_dir("index.html"))).to be_truthy
64
- end
65
- it "exports svg" do
66
- data = @data.xpath("//svg")
67
- expect(data).to be_truthy
68
- expect(data.first).to be_truthy
69
- expect(@base).to be_truthy
70
- expect(@base["width"]).to be_falsy #width property should be stripped
71
- expect(@base["height"]).to be_falsy
72
- # Do not strip other width and height attributes
73
- end
74
- it "parse relative paths" do
75
- data = @data.css("#path").css("svg")
76
- expect(data.size).to eq(2)
77
- expect(data[0].to_html).to eq(data[1].to_html) #should use to_xml?
78
- end
79
- it "jails to Jekyll source" do
80
- data = @data.css("#jail").css("svg")
81
- ref = @base.to_xml
82
- expect(data.size).to eq(2)
83
- data.each{ |item| expect(item.to_xml).to eql(ref) }
84
- end
85
- it "interpret variables" do
86
- data = @data.css("#interpret").css("svg")
87
- ref = @base.to_xml
88
- expect(data.size).to eq(2)
89
- expect(data[0].to_xml).to eql(ref)
90
- expect(data[1].get_attribute("id")).to eql("name-square")
91
- expect(data[1].get_attribute("class")).to eql("class-hello")
90
+ expect(data[2].get_attribute("width")).to eql("24")
91
+ end
92
+ it "parse relative paths" do
93
+ data = @data.css("#path").css("svg")
94
+ expect(data.size).to eq(2)
95
+ expect(data[0].to_html).to eq(data[1].to_html) #should use to_xml?
96
+ end
97
+ it "jails to Jekyll source" do
98
+ data = @data.css("#jail").css("svg")
99
+ ref = @base.to_xml
100
+ expect(data.size).to eq(2)
101
+ data.each{ |item| expect(item.to_xml).to eql(ref) }
102
+ end
103
+ it "interpret variables" do
104
+ data = @data.css("#interpret").css("svg")
105
+ ref = @base.to_xml
106
+ expect(data.size).to eq(2)
107
+ expect(data[0].to_xml).to eql(ref)
108
+ expect(data[1].get_attribute("id")).to eql("name-square")
109
+ expect(data[1].get_attribute("class")).to eql("class-hello")
110
+ end
111
+ it "#{is_opt ? "do" : "do not"} optimize" do
112
+ data = @data.css("#optimize").css("svg")
113
+ expect(data.first.get_attribute("data-foo")).to is_opt ? be_falsy : eql("")
114
+ expect(data.xpath("//comment()").first).to is_opt ? be_falsy : be_truthy
115
+ end
92
116
  end
93
117
  end
94
118
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-inline-svg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastien DUMETZ
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-22 00:00:00.000000000 Z
11
+ date: 2017-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll