inline_svg 1.0.0 → 1.2.0

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 inline_svg might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7004d185bef2b924f18a066874654c38df4def32
4
- data.tar.gz: b88ad5893b28740772c3561c2ec10b49f16354e8
3
+ metadata.gz: 9af50a1ce42f8f67f9df531b740b4d0f8adedc2b
4
+ data.tar.gz: 4c4399fffe814ff7587851cefd33deb3cb1910ce
5
5
  SHA512:
6
- metadata.gz: d2cd936da88bd368aa88e7da0ef68791523c3c386d746e094c7e8f3df4b8b9dd3dc2293529d10ee80a42273a82f45ae69c356d55c2ada0ead4c59fcdfe64ed33
7
- data.tar.gz: efdcb9cdbd557a06a0b689563b469df1fb1d7e8d78b62cc7cad97f70e26fb6f0c2d72f624ae7b36301a45298326ee043c401cc34b8e3bded752a886a14d62def
6
+ metadata.gz: d0facb0d977943f429edd52e7ac6307b3c092dd53a16bd694214048157a3b128cbdd6eb8c168f9a71889837a4427e30b1e97ffffd4b55fd353c87e6aae798fca
7
+ data.tar.gz: 1e3e2fe9c6f563bd654fbbba92a216eef5efa340f2d755807ad2934d4b1bccf1bb70877f8ee74e2e1c5192aa8edef894f175f19890c76e6882eeec9e25deab48
data/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@ This project adheres to [Semantic Versioning](http://semver.org/).
5
5
  ## [Unreleased][unreleased]
6
6
  - Nothing
7
7
 
8
+ ## [1.2.0] - 2017-04-20
9
+ ### Added
10
+ - Cached asset file (load assets into memory at boot time)
11
+ [#62](https://github.com/jamesmartin/inline_svg/pull/62)
12
+
13
+ ## [1.1.0] - 2017-04-12
14
+ ### Added
15
+ - Allow configurable asset file implementations
16
+ [#61](https://github.com/jamesmartin/inline_svg/pull/61)
17
+
18
+ ## [1.0.1] - 2017-04-10
19
+ ### Fixed
20
+ - Don't override custom asset finders in Railtie
21
+
8
22
  ## [1.0.0] - 2017-04-7
9
23
  ### Added
10
24
  - Remove dependency on `Loofah` while maintaining basic `nocomment` transform
@@ -140,7 +154,10 @@ transformations](https://github.com/jamesmartin/inline_svg/blob/master/README.md
140
154
  ### Added
141
155
  - Basic Railtie and view helper to inline SVG documents to Rails views.
142
156
 
143
- [unreleased]: https://github.com/jamesmartin/inline_svg/compare/v1.0.0...HEAD
157
+ [unreleased]: https://github.com/jamesmartin/inline_svg/compare/v1.2.0...HEAD
158
+ [1.2.0]: https://github.com/jamesmartin/inline_svg/compare/v1.1.0...v1.2.0
159
+ [1.1.0]: https://github.com/jamesmartin/inline_svg/compare/v1.0.1...v1.1.0
160
+ [1.0.1]: https://github.com/jamesmartin/inline_svg/compare/v1.0.0...v1.0.1
144
161
  [1.0.0]: https://github.com/jamesmartin/inline_svg/compare/v0.12.1...v1.0.0
145
162
  [0.12.1]: https://github.com/jamesmartin/inline_svg/compare/v0.12.0...v0.12.1
146
163
  [0.12.0]: https://github.com/jamesmartin/inline_svg/compare/v0.11.1...v0.12.0
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Inline SVG
2
2
 
3
+ [![CircleCI](https://circleci.com/gh/jamesmartin/inline_svg.svg?style=svg)](https://circleci.com/gh/jamesmartin/inline_svg)
4
+
3
5
  Styling a SVG document with CSS for use on the web is most reliably achieved by
4
6
  [adding classes to the document and
5
7
  embedding](http://css-tricks.com/using-svg/) it inline in the HTML.
@@ -40,18 +42,20 @@ actual path of the file on disk is resolved using
40
42
  [Sprockets](://github.com/sstephenson/sprockets) (when available), a naive file finder (`/public/assets/...`) or in the case of `IO` objects the SVG data is read from the object.
41
43
  This means you can pre-process and fingerprint your SVG files like other Rails assets, or choose to find SVG data yourself.
42
44
 
43
- Here's an example of embedding an SVG document and applying a 'class' attribute in
44
- HAML:
45
+ Here's an example of embedding an SVG document and applying a 'class' attribute:
45
46
 
46
- ```haml
47
- !!! 5
48
- %html
49
- %head
50
- %title Embedded SVG Documents
51
- %body
52
- %h1 Embedded SVG Documents
53
- %div
54
- = inline_svg "some-document.svg", class: 'some-class'
47
+ ```erb
48
+ <html>
49
+ <head>
50
+ <title>Embedded SVG Documents<title>
51
+ </head>
52
+ <body>
53
+ <h1>Embedded SVG Documents</h1>
54
+ <div>
55
+ <%= inline_svg "some-document.svg", class: 'some-class' %>
56
+ </div>
57
+ </body>
58
+ </html>
55
59
  ```
56
60
 
57
61
  Here's some CSS to target the SVG, resize it and turn it an attractive shade of
@@ -201,6 +205,58 @@ Transforms are applied in ascending order (lowest number first).
201
205
  ***Note***: Custom transformations are always applied *after* all built-in
202
206
  transformations, regardless of priority.
203
207
 
208
+ ## Custom asset file loader
209
+
210
+ An asset file loader returns a `String` representing a SVG document given a
211
+ filename. Custom asset loaders should be a Ruby object that responds to a
212
+ method called `named`, that takes one argument (a string representing the
213
+ filename of the SVG document).
214
+
215
+ A simple example might look like this:
216
+
217
+ ```ruby
218
+ class MyAssetFileLoader
219
+ def self.named(filename)
220
+ # ... load SVG document however you like
221
+ return "<svg>some document</svg>"
222
+ end
223
+ end
224
+ ```
225
+
226
+ Configure your custom asset file loader in an initializer like so:
227
+
228
+ ```ruby
229
+ InlineSvg.configure do |config|
230
+ config.asset_file = MyAssetFileLoader
231
+ end
232
+ ```
233
+
234
+ ## Caching all assets at boot time
235
+
236
+ When your deployment strategy prevents dynamic asset file loading from disk it
237
+ can be helpful to cache all possible SVG assets in memory at application boot
238
+ time. In this case, you can configure the `InlineSvg::CachedAssetFile` to scan
239
+ any number of paths on disks and load all the assets it finds into memory.
240
+
241
+ For example, in this configuration we load every `*.svg` file found beneath the
242
+ configured paths into memory:
243
+
244
+ ```ruby
245
+ InlineSvg.configure do |config|
246
+ config.asset_file = InlineSvg::CachedAssetFile.new(
247
+ paths: [
248
+ "#{Rails.root}/public/path/to/assets",
249
+ "#{Rails.root}/public/other/path/to/assets"
250
+ ],
251
+ filters: /\.svg/
252
+ )
253
+ end
254
+ ```
255
+
256
+ **Note:** Paths are read recursively, so think about keeping your SVG assets
257
+ restricted to as few paths as possible, and using the filter option to further
258
+ restrict assets to only those likely to be used by `inline_svg`.
259
+
204
260
  ## Contributing
205
261
 
206
262
  1. Fork it ( [http://github.com/jamesmartin/inline_svg/fork](http://github.com/jamesmartin/inline_svg/fork) )
@@ -9,7 +9,7 @@ module InlineSvg
9
9
  svg_file = if InlineSvg::IOResource === filename
10
10
  InlineSvg::IOResource.read filename
11
11
  else
12
- InlineSvg::AssetFile.named filename
12
+ configured_asset_file.named filename
13
13
  end
14
14
  rescue InlineSvg::AssetFile::FileNotFound
15
15
  return "<svg><!-- SVG file not found: '#{filename}' #{extension_hint(filename)}--></svg>".html_safe
@@ -20,6 +20,10 @@ module InlineSvg
20
20
 
21
21
  private
22
22
 
23
+ def configured_asset_file
24
+ InlineSvg.configuration.asset_file
25
+ end
26
+
23
27
  def extension_hint(filename)
24
28
  filename.ends_with?(".svg") ? "" : "(Try adding .svg to your filename) "
25
29
  end
@@ -0,0 +1,66 @@
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
+ end
22
+
23
+ # Public: Finds the named asset and returns the contents as a string.
24
+ #
25
+ # asset_name - A string representing the name of the asset to load
26
+ #
27
+ # Returns: A String or raises InlineSvg::AssetFile::FileNotFound error
28
+ def named(asset_name)
29
+ assets[key_for_asset(asset_name)] or
30
+ raise InlineSvg::AssetFile::FileNotFound.new("Asset not found: #{asset_name}")
31
+ end
32
+
33
+ private
34
+ # Internal: Finds the key for a given asset name (using a Regex).
35
+ #
36
+ # Returns a String representing the key for the named asset.
37
+ def key_for_asset(asset_name)
38
+ assets.keys.map { |k| k.to_s }.select { |k| /#{asset_name}/.match(k) }.first
39
+ end
40
+
41
+ # Internal: Recursively descends through current_paths reading each file it
42
+ # finds and adding them to the accumulator if the fullpath of the file
43
+ # matches all configured filters.
44
+ #
45
+ # acc - Hash representing the accumulated assets keyed by full path
46
+ # paths - Pathname representing the current node in the directory
47
+ # structure to consider
48
+ #
49
+ # Returns a Hash containing the contents of each asset, keyed by fullpath
50
+ # to the asset.
51
+ def read_assets(acc, paths)
52
+ paths.each_child do |child|
53
+ if child.directory?
54
+ read_assets(acc, child)
55
+ elsif child.readable_real?
56
+ acc[child.to_s] = File.read(child) if matches_all_filters?(child)
57
+ end
58
+ end
59
+ acc
60
+ end
61
+
62
+ def matches_all_filters?(path)
63
+ filters.all? { |f| f.match(path.to_s) }
64
+ end
65
+ end
66
+ end
@@ -12,7 +12,11 @@ module InlineSvg
12
12
  InlineSvg.configure do |config|
13
13
  # In default Rails apps, this will be a fully operational
14
14
  # Sprockets::Environment instance
15
- config.asset_finder = app.instance_variable_get(:@assets)
15
+ # Only set this when a user-configured asset finder has not been
16
+ # configured already.
17
+ if config.asset_finder.nil?
18
+ config.asset_finder = app.instance_variable_get(:@assets)
19
+ end
16
20
  end
17
21
  end
18
22
  end
@@ -1,3 +1,3 @@
1
1
  module InlineSvg
2
- VERSION = "1.0.0"
2
+ VERSION = "1.2.0"
3
3
  end
data/lib/inline_svg.rb CHANGED
@@ -1,6 +1,7 @@
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"
6
7
  require "inline_svg/transform_pipeline"
@@ -14,10 +15,24 @@ module InlineSvg
14
15
  class Configuration
15
16
  class Invalid < ArgumentError; end
16
17
 
17
- attr_reader :asset_finder, :custom_transformations
18
+ attr_reader :asset_file, :asset_finder, :custom_transformations
18
19
 
19
20
  def initialize
20
21
  @custom_transformations = {}
22
+ @asset_file = InlineSvg::AssetFile
23
+ end
24
+
25
+ def asset_file=(custom_asset_file)
26
+ begin
27
+ method = custom_asset_file.method(:named)
28
+ if method.arity == 1
29
+ @asset_file = custom_asset_file
30
+ else
31
+ raise InlineSvg::Configuration::Invalid.new("asset_file should implement the #named method with arity 1")
32
+ end
33
+ rescue NameError
34
+ raise InlineSvg::Configuration::Invalid.new("asset_file should implement the #named method")
35
+ end
21
36
  end
22
37
 
23
38
  def asset_finder=(finder)
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+ require 'pathname'
3
+ require_relative '../lib/inline_svg'
4
+
5
+ describe InlineSvg::CachedAssetFile do
6
+ let(:fixture_path) { Pathname.new(File.expand_path("../files/static_assets", __FILE__)) }
7
+
8
+ it "loads assets under configured paths" do
9
+ known_document = File.read(fixture_path.join("assets0", "known-document.svg"))
10
+
11
+ asset_loader = InlineSvg::CachedAssetFile.new(paths: fixture_path.join("assets0"))
12
+
13
+ expect(asset_loader.named("known-document.svg")).to eq(known_document)
14
+ end
15
+
16
+ it "does not include assets outside of configured paths" do
17
+ asset_loader = InlineSvg::CachedAssetFile.new(paths: fixture_path.join("assets0"))
18
+
19
+ expect(fixture_path.join("assets1", "other-document.svg")).to be_file
20
+ expect do
21
+ asset_loader.named("other-document.svg")
22
+ end.to raise_error InlineSvg::AssetFile::FileNotFound
23
+ end
24
+
25
+ it "differentiates two files with the same name" do
26
+ known_document_0 = File.read(fixture_path.join("assets0", "known-document.svg"))
27
+ known_document_1 = File.read(fixture_path.join("assets1", "known-document.svg"))
28
+
29
+ expect(known_document_0).not_to eq(known_document_1)
30
+
31
+ asset_loader = InlineSvg::CachedAssetFile.new(paths: fixture_path)
32
+
33
+ expect(known_document_0).to eq(asset_loader.named("assets0/known-document.svg"))
34
+ expect(known_document_1).to eq(asset_loader.named("assets1/known-document.svg"))
35
+ end
36
+
37
+ it "filters wanted files by simple string matching" do
38
+ known_document_0 = File.read(fixture_path.join("assets0", "known-document.svg"))
39
+ known_document_1 = File.read(fixture_path.join("assets1", "known-document.svg"))
40
+
41
+ asset_loader = InlineSvg::CachedAssetFile.new(paths: fixture_path, filters: "assets1")
42
+
43
+ expect do
44
+ asset_loader.named("assets0/known-document.svg")
45
+ end.to raise_error InlineSvg::AssetFile::FileNotFound
46
+
47
+ expect(known_document_1).to eq(asset_loader.named("assets1/known-document.svg"))
48
+ end
49
+
50
+ it "filters wanted files by regex matching" do
51
+ known_document_1 = File.read(fixture_path.join("assets1", "known-document.svg"))
52
+
53
+ asset_loader = InlineSvg::CachedAssetFile.new(paths: fixture_path, filters: ["assets1", /\.svg/])
54
+
55
+ expect do
56
+ asset_loader.named("assets1/some-file.txt")
57
+ end.to raise_error InlineSvg::AssetFile::FileNotFound
58
+
59
+ expect(known_document_1).to eq(asset_loader.named("assets1/known-document.svg"))
60
+ end
61
+ end
@@ -0,0 +1 @@
1
+ <svg>interesting content</svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M3.273 7.151l-2.917-2.916c-.23.665-.356 1.361-.356 2.057 0 1.608.624 3.216 1.851 4.442 1.35 1.351 3.163 1.957 4.928 1.821.933-.072 1.851.268 2.513.93l9.646 9.646c.58.579 1.338.869 2.097.869 1.636 0 2.965-1.326 2.965-2.965 0-.759-.29-1.518-.868-2.097l-9.647-9.646c-.661-.662-1.002-1.581-.93-2.514.136-1.766-.47-3.578-1.821-4.928-.372-.372-.778-.686-1.209-.945l-6.252 6.246zm18.727 13.849c0 .552-.448 1-1 1s-1-.448-1-1 .448-1 1-1 1 .447 1 1zm-12.153-13.396l-3.061 3.061-2.566-2.567 3.062-3.061 2.565 2.567zm-.933.096l-.762.761-1.705-1.705.762-.762 1.705 1.706zm-2.991-.42l-.761.762 1.706 1.705.762-.762-1.707-1.705zm2.484-6.903l-2.893 2.893-2.412-2.412c.953-.556 2.044-.858 3.165-.858.707 0 1.425.12 2.128.373l.012.004z"/></svg>
@@ -0,0 +1 @@
1
+ <svg>Another known document</svg>
@@ -0,0 +1,3 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg>Other document</svg>
@@ -0,0 +1 @@
1
+ Some file contents.
@@ -13,6 +13,10 @@ class MyInvalidCustomTransformInstance
13
13
  def self.create_with_value(value); end
14
14
  end
15
15
 
16
+ class MyCustomAssetFile
17
+ def self.named(filename); end
18
+ end
19
+
16
20
  describe InlineSvg do
17
21
  describe "configuration" do
18
22
  context "when a block is not given" do
@@ -42,6 +46,40 @@ describe InlineSvg do
42
46
  end
43
47
  end
44
48
 
49
+ context "configuring a custom asset file" do
50
+ it "falls back to the built-in asset file implementation by deafult" do
51
+ expect(InlineSvg.configuration.asset_file).to eq(InlineSvg::AssetFile)
52
+ end
53
+
54
+ it "adds a collaborator that meets the interface specification" do
55
+ InlineSvg.configure do |config|
56
+ config.asset_file = MyCustomAssetFile
57
+ end
58
+
59
+ expect(InlineSvg.configuration.asset_file).to eq MyCustomAssetFile
60
+ end
61
+
62
+ it "rejects a collaborator that does not conform to the interface spec" do
63
+ bad_asset_file = double("bad_asset_file")
64
+
65
+ expect do
66
+ InlineSvg.configure do |config|
67
+ config.asset_file = bad_asset_file
68
+ end
69
+ end.to raise_error(InlineSvg::Configuration::Invalid, /asset_file should implement the #named method/)
70
+ end
71
+
72
+ it "rejects a collaborator that implements the correct interface with the wrong arity" do
73
+ bad_asset_file = double("bad_asset_file", named: nil)
74
+
75
+ expect do
76
+ InlineSvg.configure do |config|
77
+ config.asset_file = bad_asset_file
78
+ end
79
+ end.to raise_error(InlineSvg::Configuration::Invalid, /asset_file should implement the #named method with arity 1/)
80
+ end
81
+ end
82
+
45
83
  context "configuring custom transformation" do
46
84
  it "allows a custom transformation to be added" do
47
85
  InlineSvg.configure do |config|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inline_svg
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Martin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-07 00:00:00.000000000 Z
11
+ date: 2017-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -126,6 +126,7 @@ files:
126
126
  - lib/inline_svg.rb
127
127
  - lib/inline_svg/action_view/helpers.rb
128
128
  - lib/inline_svg/asset_file.rb
129
+ - lib/inline_svg/cached_asset_file.rb
129
130
  - lib/inline_svg/finds_asset_paths.rb
130
131
  - lib/inline_svg/id_generator.rb
131
132
  - lib/inline_svg/io_resource.rb
@@ -147,7 +148,13 @@ files:
147
148
  - lib/inline_svg/transform_pipeline/transformations/width.rb
148
149
  - lib/inline_svg/version.rb
149
150
  - spec/asset_file_spec.rb
151
+ - spec/cached_asset_file_spec.rb
150
152
  - spec/files/example.svg
153
+ - spec/files/static_assets/assets0/known-document.svg
154
+ - spec/files/static_assets/assets0/some-document.svg
155
+ - spec/files/static_assets/assets1/known-document.svg
156
+ - spec/files/static_assets/assets1/other-document.svg
157
+ - spec/files/static_assets/assets1/some-file.txt
151
158
  - spec/finds_asset_paths_spec.rb
152
159
  - spec/helpers/inline_svg_spec.rb
153
160
  - spec/id_generator_spec.rb
@@ -190,7 +197,13 @@ specification_version: 4
190
197
  summary: Embeds an SVG document, inline.
191
198
  test_files:
192
199
  - spec/asset_file_spec.rb
200
+ - spec/cached_asset_file_spec.rb
193
201
  - spec/files/example.svg
202
+ - spec/files/static_assets/assets0/known-document.svg
203
+ - spec/files/static_assets/assets0/some-document.svg
204
+ - spec/files/static_assets/assets1/known-document.svg
205
+ - spec/files/static_assets/assets1/other-document.svg
206
+ - spec/files/static_assets/assets1/some-file.txt
194
207
  - spec/finds_asset_paths_spec.rb
195
208
  - spec/helpers/inline_svg_spec.rb
196
209
  - spec/id_generator_spec.rb