esvg 4.1.0 → 4.1.1
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 +4 -4
- data/lib/esvg/helpers.rb +3 -3
- data/lib/esvg/svg.rb +90 -81
- data/lib/esvg/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27d93663b8b9b36654390502132bf232efe68c66
|
4
|
+
data.tar.gz: 43344a22127df181e71d73602dbe0764e51d13e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc486ddf04d4b6692407740dc3d1c808181587ce8d92c0e3a78b33c35c4631d1913b961d649b2179e4e9378d4c230e2d8c53cf8e513568246511686387e3c7b2
|
7
|
+
data.tar.gz: 1d1e3f0476e4c2dee4eb68d2814712407b0e84eb8faf1e5bd49b9b5729bfa95181c106ce5ddd98e6053bb54245907702d8bfe07992dcb2c337d573f7eb65eb20
|
data/lib/esvg/helpers.rb
CHANGED
@@ -10,10 +10,10 @@ module Esvg::Helpers
|
|
10
10
|
|
11
11
|
|
12
12
|
def embed_svgs(*keys)
|
13
|
-
if Rails.env.production?
|
14
|
-
esvg.build_paths(keys).
|
13
|
+
if !Rails.env.production?
|
14
|
+
esvg.build_paths(keys).map do |path|
|
15
15
|
javascript_include_tag(path)
|
16
|
-
end.join("\n")
|
16
|
+
end.join("\n").html_safe
|
17
17
|
else
|
18
18
|
esvg.embed_script(keys).html_safe
|
19
19
|
end
|
data/lib/esvg/svg.rb
CHANGED
@@ -22,7 +22,7 @@ module Esvg
|
|
22
22
|
CONFIG_RAILS = {
|
23
23
|
source: "app/assets/svgs",
|
24
24
|
assets: "app/assets/javascripts",
|
25
|
-
build: "public/
|
25
|
+
build: "public/javascripts",
|
26
26
|
temp: "tmp"
|
27
27
|
}
|
28
28
|
|
@@ -77,7 +77,6 @@ module Esvg
|
|
77
77
|
# Get a list of svg files and modification times
|
78
78
|
#
|
79
79
|
find_files
|
80
|
-
write_cache
|
81
80
|
|
82
81
|
@last_read = Time.now.to_i
|
83
82
|
|
@@ -90,6 +89,7 @@ module Esvg
|
|
90
89
|
|
91
90
|
def find_files
|
92
91
|
files = Dir[File.join(config[:source], '**/*.svg')].uniq.sort
|
92
|
+
@svg_symbols = {}
|
93
93
|
|
94
94
|
# Remove deleted files from svg cache
|
95
95
|
(svgs.keys - file_keys(files)).each { |f| svgs.delete(f) }
|
@@ -97,16 +97,18 @@ module Esvg
|
|
97
97
|
dirs = {}
|
98
98
|
|
99
99
|
files.each do |path|
|
100
|
-
|
101
100
|
mtime = File.mtime(path).to_i
|
102
101
|
key = file_key path
|
103
102
|
dkey = dir_key path
|
104
103
|
|
105
104
|
# Use cache if possible
|
106
105
|
if svgs[key].nil? || svgs[key][:last_modified] != mtime
|
107
|
-
svgs[key] = process_file(path, mtime
|
106
|
+
svgs[key] = process_file(path, mtime)
|
108
107
|
end
|
109
108
|
|
109
|
+
# Name may have changed due to flatten config
|
110
|
+
svgs[key][:name] = file_name(path)
|
111
|
+
|
110
112
|
dirs[dkey] ||= {}
|
111
113
|
(dirs[dkey][:files] ||= []) << key
|
112
114
|
|
@@ -117,31 +119,22 @@ module Esvg
|
|
117
119
|
|
118
120
|
dirs = sort(dirs)
|
119
121
|
|
120
|
-
# Remove deleted directories from svg_symbols cache
|
121
|
-
(svg_symbols.keys - dirs.keys).each {|dir| svg_symbols.delete(dir) }
|
122
|
-
|
123
122
|
dirs.each do |dir, data|
|
124
123
|
|
125
124
|
# overwrite cache if
|
126
125
|
if svg_symbols[dir].nil? || # No cache for this dir yet
|
127
126
|
svg_symbols[dir][:last_modified] != data[:last_modified] || # New or updated file
|
128
|
-
svg_symbols[dir][:optimized] != optimize? || # Cache is unoptimized
|
129
127
|
svg_symbols[dir][:files] != data[:files] # Changed files
|
130
128
|
|
131
|
-
symbols = data[:files].map { |f| svgs[f][:content] }.join
|
132
129
|
attributes = data[:files].map { |f| svgs[f][:attr] }
|
130
|
+
mtimes = data[:files].map { |f| svgs[f][:last_modified] }.join
|
133
131
|
|
134
132
|
svg_symbols[dir] = data.merge({
|
135
133
|
name: dir,
|
136
|
-
|
137
|
-
|
138
|
-
version: config[:version] || Digest::MD5.hexdigest(symbols),
|
139
|
-
asset: File.basename(dir).start_with?('_')
|
134
|
+
asset: File.basename(dir).start_with?('_'),
|
135
|
+
version: config[:version] || Digest::MD5.hexdigest(mtimes)
|
140
136
|
})
|
141
137
|
|
142
|
-
end
|
143
|
-
|
144
|
-
svg_symbols.keys.each do |dir|
|
145
138
|
svg_symbols[dir][:path] = write_path(dir)
|
146
139
|
end
|
147
140
|
end
|
@@ -152,15 +145,12 @@ module Esvg
|
|
152
145
|
|
153
146
|
def read_cache
|
154
147
|
@svgs = YAML.load(read_tmp '.svgs') || {}
|
155
|
-
@svg_symbols = YAML.load(read_tmp '.svg_symbols') || {}
|
156
148
|
end
|
157
149
|
|
158
150
|
def write_cache
|
159
151
|
return if production?
|
160
152
|
|
161
153
|
write_tmp '.svgs', sort(@svgs).to_yaml
|
162
|
-
write_tmp '.svg_symbols', sort(@svg_symbols).to_yaml
|
163
|
-
|
164
154
|
end
|
165
155
|
|
166
156
|
def sort(hash)
|
@@ -195,26 +185,22 @@ module Esvg
|
|
195
185
|
end.map { |k| svg_symbols[k] }
|
196
186
|
end
|
197
187
|
|
198
|
-
def process_file(
|
199
|
-
content = File.read(
|
200
|
-
id = id(
|
188
|
+
def process_file(path, mtime)
|
189
|
+
content = File.read(path)
|
190
|
+
id = id(file_key(path))
|
201
191
|
size_attr = dimensions(content)
|
202
192
|
|
203
|
-
|
204
|
-
|
193
|
+
{
|
194
|
+
path: path,
|
205
195
|
use: %Q{<use xlink:href="##{id}"/>},
|
206
196
|
last_modified: mtime,
|
207
|
-
attr: { id: id }.merge(size_attr)
|
197
|
+
attr: { id: id }.merge(size_attr),
|
198
|
+
content: content
|
208
199
|
}
|
209
|
-
# Add attributes
|
210
|
-
svg[:content] = prep_svg(content, svg[:attr])
|
211
|
-
|
212
|
-
svg
|
213
200
|
end
|
214
201
|
|
215
202
|
def use(file, options={})
|
216
|
-
if
|
217
|
-
svg = svgs[name]
|
203
|
+
if svg = find_svg(file, options[:fallback])
|
218
204
|
|
219
205
|
if options[:color]
|
220
206
|
options[:style] ||= ''
|
@@ -225,7 +211,7 @@ module Esvg
|
|
225
211
|
fill: options[:fill],
|
226
212
|
style: options[:style],
|
227
213
|
viewBox: svg[:attr][:viewBox],
|
228
|
-
class: [config[:class], svg[:
|
214
|
+
class: [config[:class], id(svg[:name]), options[:class]].compact.join(' ')
|
229
215
|
}
|
230
216
|
|
231
217
|
# If user doesn't pass a size or set scale: true
|
@@ -283,14 +269,17 @@ module Esvg
|
|
283
269
|
end
|
284
270
|
|
285
271
|
def exist?(name, fallback=nil)
|
272
|
+
!find_svg(name, fallback).nil?
|
273
|
+
end
|
274
|
+
|
275
|
+
def find_svg(name, fallback=nil)
|
286
276
|
name = get_alias dasherize(name)
|
287
277
|
|
288
|
-
if svgs[name]
|
289
|
-
|
290
|
-
|
291
|
-
|
278
|
+
if svg = svgs.values.find { |v| v[:name] == name }
|
279
|
+
svg
|
280
|
+
elsif fallback
|
281
|
+
find_svg(fallback)
|
292
282
|
end
|
293
|
-
|
294
283
|
end
|
295
284
|
|
296
285
|
alias_method :exists?, :exist?
|
@@ -344,7 +333,9 @@ module Esvg
|
|
344
333
|
paths = []
|
345
334
|
|
346
335
|
files.each do |file|
|
347
|
-
|
336
|
+
content = js(file[:name])
|
337
|
+
|
338
|
+
write_file(file[:path], content)
|
348
339
|
puts "Writing #{file[:path]}" if config[:print]
|
349
340
|
paths << file[:path]
|
350
341
|
|
@@ -354,17 +345,29 @@ module Esvg
|
|
354
345
|
end
|
355
346
|
end
|
356
347
|
|
348
|
+
write_cache
|
349
|
+
|
357
350
|
paths
|
358
351
|
end
|
359
352
|
|
360
353
|
def symbols(keys)
|
361
354
|
symbols = valid_keys(keys).map { |key|
|
362
|
-
|
355
|
+
# Build on demand
|
356
|
+
build_symbols(svg_symbols[key][:files])
|
363
357
|
}.join.gsub(/\n/,'')
|
364
358
|
|
365
359
|
%Q{<svg id="esvg-#{key_id(keys)}" version="1.1" style="height:0;position:absolute">#{symbols}</svg>}
|
366
360
|
end
|
367
361
|
|
362
|
+
def build_symbols(files)
|
363
|
+
files.map { |file|
|
364
|
+
if svgs[file][:optimized_at].nil? || svgs[file][:optimized_at] < svgs[file][:last_modified]
|
365
|
+
svgs[file][:optimized_content] = optimize(svgs[file])
|
366
|
+
end
|
367
|
+
svgs[file][:optimized_content]
|
368
|
+
}.join.gsub(/\n/,'')
|
369
|
+
end
|
370
|
+
|
368
371
|
def js(key)
|
369
372
|
keys = valid_keys(key)
|
370
373
|
return if keys.empty?
|
@@ -471,10 +474,16 @@ module Esvg
|
|
471
474
|
|
472
475
|
private
|
473
476
|
|
477
|
+
def file_key(path)
|
478
|
+
dasherize sub_path(path).sub('.svg','')
|
479
|
+
end
|
480
|
+
|
474
481
|
def dir_key(path)
|
475
482
|
dir = File.dirname(flatten_path(path))
|
476
483
|
|
477
484
|
# Flattened paths which should be treated as assets will use '_' as their dir key
|
485
|
+
# - flatten: _foo - _foo/icon.svg will have a dirkey of _
|
486
|
+
# - filename: _icons - treats all root or flattened files as assets
|
478
487
|
if dir == '.' && ( sub_path(path).start_with?('_') || config[:filename].start_with?('_') )
|
479
488
|
'_'
|
480
489
|
else
|
@@ -482,6 +491,10 @@ module Esvg
|
|
482
491
|
end
|
483
492
|
end
|
484
493
|
|
494
|
+
def file_name(path)
|
495
|
+
dasherize flatten_path(path).sub('.svg','')
|
496
|
+
end
|
497
|
+
|
485
498
|
def sub_path(path)
|
486
499
|
path.sub("#{config[:source]}/",'')
|
487
500
|
end
|
@@ -490,10 +503,6 @@ module Esvg
|
|
490
503
|
sub_path(path).sub(Regexp.new(config[:flatten]), '')
|
491
504
|
end
|
492
505
|
|
493
|
-
def file_key(path)
|
494
|
-
dasherize flatten_path(path).sub('.svg', '')
|
495
|
-
end
|
496
|
-
|
497
506
|
def file_keys(paths)
|
498
507
|
paths.flatten.map { |p| file_key(p) }
|
499
508
|
end
|
@@ -518,31 +527,60 @@ module Esvg
|
|
518
527
|
end
|
519
528
|
end
|
520
529
|
|
521
|
-
def
|
522
|
-
|
530
|
+
def svgo?
|
531
|
+
!!(config[:optimize] && svgo_cmd)
|
532
|
+
end
|
533
|
+
|
534
|
+
def optimize(svg)
|
535
|
+
svg[:optimized_content] = pre_optimize svg[:content]
|
536
|
+
svg[:optimized_content] = sub_def_ids svg
|
537
|
+
|
538
|
+
if svgo?
|
539
|
+
response = Open3.capture3(%Q{#{} --disable=removeUselessDefs -s '#{svg[:content]}' -o -})
|
540
|
+
svg[:optimized_content] = response[0] if response[2].success?
|
541
|
+
end
|
542
|
+
|
543
|
+
svg[:optimized_at] = Time.now.to_i
|
544
|
+
svg[:optimized_content] = post_optimize svg
|
545
|
+
end
|
546
|
+
|
547
|
+
def pre_optimize(svg)
|
548
|
+
reg = %w(xmlns xmlns:xlink xml:space version).map { |m| "#{m}=\".+?\"" }.join('|')
|
549
|
+
svg.gsub(Regexp.new(reg), '') # Remove unwanted attributes
|
550
|
+
.gsub(/<?.+\?>/,'').gsub(/<!.+?>/,'') # Get rid of doctypes and comments
|
523
551
|
.gsub(/\n/, '') # Remove endlines
|
524
552
|
.gsub(/\s{2,}/, ' ') # Remove whitespace
|
525
553
|
.gsub(/>\s+</, '><') # Remove whitespace between tags
|
526
554
|
.gsub(/\s?fill="(#0{3,6}|black|rgba?\(0,0,0\))"/,'') # Strip black fill
|
527
555
|
.gsub(/style="([^"]*?)fill:(.+?);/m, 'fill="\2" style="\1') # Make fill a property instead of a style
|
528
556
|
.gsub(/style="([^"]*?)fill-opacity:(.+?);/m, 'fill-opacity="\2" style="\1') # Move fill-opacity a property instead of a style
|
557
|
+
end
|
529
558
|
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
content = set_attributes content, attr
|
534
|
-
content.gsub(/<\/svg/,'</symbol') # Replace svgs with symbols
|
559
|
+
def post_optimize(svg)
|
560
|
+
svg[:optimized_content] = set_attributes(svg)
|
561
|
+
.gsub(/<\/svg/,'</symbol') # Replace svgs with symbols
|
535
562
|
.gsub(/class="def-/,'id="def-') # Replace <def> classes with ids (classes are generated in sub_def_ids)
|
536
|
-
.gsub(/\s{2,}/,'') # Remove extra spaces
|
537
563
|
.gsub(/\w+=""/,'') # Remove empty attributes
|
538
564
|
end
|
539
565
|
|
566
|
+
def set_attributes(svg)
|
567
|
+
svg[:attr].keys.each { |key| svg[:optimized_content].sub!(/ #{key}=".+?"/,'') }
|
568
|
+
svg[:optimized_content].sub(/<svg/, "<symbol #{attributes(svg[:attr])}")
|
569
|
+
end
|
570
|
+
|
571
|
+
def svgo_cmd
|
572
|
+
find_node_module('svgo')
|
573
|
+
end
|
574
|
+
|
540
575
|
# Scans <def> blocks for IDs
|
541
576
|
# If urls(#id) are used, ensure these IDs are unique to this file
|
542
577
|
# Only replace IDs if urls exist to avoid replacing defs
|
543
578
|
# used in other svg files
|
544
579
|
#
|
545
|
-
def sub_def_ids(
|
580
|
+
def sub_def_ids(svg)
|
581
|
+
content = svg[:optimized_content]
|
582
|
+
name = svg[:attr][:id]
|
583
|
+
|
546
584
|
return content unless !!content.match(/<defs>/)
|
547
585
|
|
548
586
|
content.scan(/<defs>.+<\/defs>/m).flatten.each do |defs|
|
@@ -562,35 +600,6 @@ module Esvg
|
|
562
600
|
content
|
563
601
|
end
|
564
602
|
|
565
|
-
def strip_attributes(svg)
|
566
|
-
reg = %w(xmlns xmlns:xlink xml:space version).map { |m| "#{m}=\".+?\"" }.join('|')
|
567
|
-
|
568
|
-
svg.gsub(Regexp.new(reg), '')
|
569
|
-
end
|
570
|
-
|
571
|
-
def set_attributes(svg, attr)
|
572
|
-
attr.keys.each { |key| svg.sub!(/ #{key}=".+?"/,'') }
|
573
|
-
svg.sub(/<svg/, "<symbol #{attributes(attr)}")
|
574
|
-
end
|
575
|
-
|
576
|
-
def optimize?
|
577
|
-
!!(config[:optimize] && svgo_cmd)
|
578
|
-
end
|
579
|
-
|
580
|
-
def svgo_cmd
|
581
|
-
find_node_module('svgo')
|
582
|
-
end
|
583
|
-
|
584
|
-
|
585
|
-
def optimize(svg)
|
586
|
-
path = write_tmp '.svgo-tmp', svg
|
587
|
-
command = "#{svgo_cmd} --disable=removeUselessDefs '#{path}' -o -"
|
588
|
-
svg = `#{command}`
|
589
|
-
FileUtils.rm(path) if File.exist? path
|
590
|
-
|
591
|
-
svg
|
592
|
-
end
|
593
|
-
|
594
603
|
def compress(file)
|
595
604
|
return if !config[:compress]
|
596
605
|
|
data/lib/esvg/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: esvg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.
|
4
|
+
version: 4.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Mathis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-05-
|
11
|
+
date: 2017-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|