inline_svg 1.0.0 → 1.10.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.
- checksums.yaml +5 -5
- data/.github/workflows/integration_test.yml +47 -0
- data/.github/workflows/rails_6_webpacker_integration_tests.yaml +62 -0
- data/.github/workflows/ruby.yml +20 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +421 -0
- data/CHANGELOG.md +143 -3
- data/README.md +149 -30
- data/Rakefile +7 -0
- data/inline_svg.gemspec +2 -1
- data/lib/inline_svg/action_view/helpers.rb +68 -7
- data/lib/inline_svg/cached_asset_file.rb +71 -0
- data/lib/inline_svg/finds_asset_paths.rb +1 -1
- data/lib/inline_svg/id_generator.rb +12 -3
- data/lib/inline_svg/io_resource.rb +4 -3
- data/lib/inline_svg/propshaft_asset_finder.rb +16 -0
- data/lib/inline_svg/railtie.rb +8 -3
- data/lib/inline_svg/static_asset_finder.rb +5 -2
- data/lib/inline_svg/transform_pipeline/transformations/aria_attributes.rb +16 -19
- data/lib/inline_svg/transform_pipeline/transformations/aria_hidden.rb +9 -0
- data/lib/inline_svg/transform_pipeline/transformations/aria_hidden_attribute.rb +9 -0
- data/lib/inline_svg/transform_pipeline/transformations/class_attribute.rb +5 -6
- data/lib/inline_svg/transform_pipeline/transformations/data_attributes.rb +4 -5
- data/lib/inline_svg/transform_pipeline/transformations/description.rb +7 -6
- data/lib/inline_svg/transform_pipeline/transformations/height.rb +3 -4
- data/lib/inline_svg/transform_pipeline/transformations/id_attribute.rb +3 -4
- data/lib/inline_svg/transform_pipeline/transformations/no_comment.rb +4 -4
- data/lib/inline_svg/transform_pipeline/transformations/preserve_aspect_ratio.rb +3 -4
- data/lib/inline_svg/transform_pipeline/transformations/size.rb +4 -5
- data/lib/inline_svg/transform_pipeline/transformations/style_attribute.rb +11 -0
- data/lib/inline_svg/transform_pipeline/transformations/title.rb +7 -6
- data/lib/inline_svg/transform_pipeline/transformations/transformation.rb +13 -0
- data/lib/inline_svg/transform_pipeline/transformations/view_box.rb +9 -0
- data/lib/inline_svg/transform_pipeline/transformations/width.rb +3 -4
- data/lib/inline_svg/transform_pipeline/transformations.rb +11 -2
- data/lib/inline_svg/transform_pipeline.rb +1 -1
- data/lib/inline_svg/version.rb +1 -1
- data/lib/inline_svg/webpack_asset_finder.rb +60 -0
- data/lib/inline_svg.rb +46 -9
- data/spec/cached_asset_file_spec.rb +73 -0
- data/spec/files/static_assets/assets0/known-document-two.svg +1 -0
- data/spec/files/static_assets/assets0/known-document.svg +1 -0
- data/spec/files/static_assets/assets0/some-document.svg +1 -0
- data/spec/files/static_assets/assets1/known-document.svg +1 -0
- data/spec/files/static_assets/assets1/other-document.svg +3 -0
- data/spec/files/static_assets/assets1/some-file.txt +1 -0
- data/spec/finds_asset_paths_spec.rb +45 -0
- data/spec/helpers/inline_svg_spec.rb +117 -51
- data/spec/id_generator_spec.rb +5 -3
- data/spec/inline_svg_spec.rb +48 -0
- data/spec/propshaft_asset_finder_spec.rb +23 -0
- data/spec/static_asset_finder_spec.rb +25 -0
- data/spec/transformation_pipeline/transformations/aria_attributes_spec.rb +6 -6
- data/spec/transformation_pipeline/transformations/aria_hidden_attribute_spec.rb +12 -0
- data/spec/transformation_pipeline/transformations/height_spec.rb +9 -0
- data/spec/transformation_pipeline/transformations/style_attribute_spec.rb +26 -0
- data/spec/transformation_pipeline/transformations/title_spec.rb +9 -0
- data/spec/transformation_pipeline/transformations/transformation_spec.rb +39 -0
- data/spec/transformation_pipeline/transformations/view_box_spec.rb +13 -0
- data/spec/transformation_pipeline/transformations_spec.rb +7 -1
- data/spec/webpack_asset_finder_spec.rb +23 -0
- metadata +62 -10
- data/circle.yml +0 -3
data/CHANGELOG.md
CHANGED
@@ -3,7 +3,129 @@ All notable changes to this project will be documented in this file.
|
|
3
3
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
4
|
|
5
5
|
## [Unreleased][unreleased]
|
6
|
-
|
6
|
+
|
7
|
+
Nothing.
|
8
|
+
|
9
|
+
## [1.10.0] - 2024-09-03
|
10
|
+
### Added
|
11
|
+
- Support for Shakapacker. [#158](https://github.com/jamesmartin/inline_svg/pull/158). Thanks, [@tagliala](https://github.com/tagliala)
|
12
|
+
|
13
|
+
### Fixed
|
14
|
+
- Fixed documentation typos. [#157](https://github.com/jamesmartin/inline_svg/pull/157). Thanks, [@tagliala](https://github.com/tagliala)
|
15
|
+
- Fixed missing ActiveSupport require. [#152](https://github.com/jamesmartin/inline_svg/pull/152). Thanks, [@xymbol](https://github.com/xymbol)
|
16
|
+
- Remove wrapping whitespace from SVG tags. [#150](https://github.com/jamesmartin/inline_svg/pull/150). Thanks, [@fredboyle](https://github.com/fredboyle)
|
17
|
+
|
18
|
+
## [1.9.0] - 2023-03-29
|
19
|
+
### Added
|
20
|
+
- A new option: `view_box` adds a `viewBox` attribute to the SVG. [#142](https://github.com/jamesmartin/inline_svg/pull/142). Thanks [@sunny](https://github.com/sunny)
|
21
|
+
|
22
|
+
### Fixed
|
23
|
+
- Allow Propshaft assets to use fallbacks. [#140](https://github.com/jamesmartin/inline_svg/pull/140). Thanks, [@ohrite](https://github.com/ohrite)
|
24
|
+
- Handling missing file when using static assets. [#141](https://github.com/jamesmartin/inline_svg/pull/141). Thanks, [@leighhalliday](https://github.com/leighhalliday)
|
25
|
+
- Handle missing file when using Webpacker assets.
|
26
|
+
|
27
|
+
## [1.8.0] - 2022-01-09
|
28
|
+
### Added
|
29
|
+
- Remove deprecation warning for `inline_svg`, as we intend to keep it in 2.0. [#131](https://github.com/jamesmartin/inline_svg/pull/131). Thanks [@DanielJackson-Oslo](https://github.com/DanielJackson-Oslo)
|
30
|
+
- Add support for Webpacker 6 beta. [#129](https://github.com/jamesmartin/inline_svg/pull/129). Thanks [@Intrepidd](https://github.com/Intrepidd) and [@tessi](https://github.com/tessi)
|
31
|
+
- Add support for Propshaft assets in Rails 7. [#134](https://github.com/jamesmartin/inline_svg/pull/134). Thanks, [@martinzamuner](https://github.com/martinzamuner)
|
32
|
+
|
33
|
+
## [1.7.2] - 2020-12-07
|
34
|
+
### Fixed
|
35
|
+
- Improve performance of `CachedAssetFile`. [#118](https://github.com/jamesmartin/inline_svg/pull/118). Thanks [@stevendaniels](https://github.com/stevendaniels)
|
36
|
+
- Avoid XSS by preventing malicious input of filenames. [#117](https://github.com/jamesmartin/inline_svg/pull/117). Thanks [@pbyrne](https://github.com/pbyrne).
|
37
|
+
|
38
|
+
## [1.7.1] - 2020-03-17
|
39
|
+
### Fixed
|
40
|
+
- Static Asset Finder uses pathname for compatibility with Sprockets 4+. [#106](https://github.com/jamesmartin/inline_svg/pull/106). Thanks [@subdigital](https://github.com/subdigital)
|
41
|
+
|
42
|
+
## [1.7.0] - 2020-02-13
|
43
|
+
### Added
|
44
|
+
- WebpackAssetFinder serves files from dev server if one is running. [#111](https://github.com/jamesmartin/inline_svg/pull/111). Thanks, [@connorshea](https://github.com/connorshea)
|
45
|
+
|
46
|
+
### Fixed
|
47
|
+
- Using Webpacker and Asset Pipeline in a single App could result in SVGs not being found because the wrong `AssetFinder` was used. [#114](https://github.com/jamesmartin/inline_svg/pull/114). Thanks, [@kylefox](https://github.com/kylefox)
|
48
|
+
- Prevent "EOFError error" when using webpack dev server over HTTPS [#113](https://github.com/jamesmartin/inline_svg/pull/113). Thanks, [@kylefox](https://github.com/kylefox)
|
49
|
+
|
50
|
+
## [1.6.0] - 2019-11-13
|
51
|
+
### Added
|
52
|
+
- Support Webpack via the new `inline_svg_pack_tag` helper and deprecate `inline_svg` helper in preparation for v2.0.
|
53
|
+
[#103](https://github.com/jamesmartin/inline_svg/pull/103)
|
54
|
+
Thanks, [@kylefox](https://github.com/kylefox)
|
55
|
+
|
56
|
+
## [1.5.2] - 2019-06-20
|
57
|
+
### Fixed
|
58
|
+
- Revert automatic Webpack asset finder behavior. Make Webpack "opt-in".
|
59
|
+
[#98](https://github.com/jamesmartin/inline_svg/issues/98)
|
60
|
+
|
61
|
+
## [1.5.1] - 2019-06-18
|
62
|
+
### Fixed
|
63
|
+
- Prevent nil asset finder when neither Sprockets or Webpacker are available
|
64
|
+
[#97](https://github.com/jamesmartin/inline_svg/issues/97)
|
65
|
+
|
66
|
+
## [1.5.0] - 2019-06-17
|
67
|
+
### Added
|
68
|
+
- Support for finding assets bundled by Webpacker
|
69
|
+
[#96](https://github.com/jamesmartin/inline_svg/pull/96)
|
70
|
+
|
71
|
+
## [1.4.0] - 2019-04-19
|
72
|
+
### Fixed
|
73
|
+
- Prevent invalid XML names being generated via IdGenerator
|
74
|
+
[#87](https://github.com/jamesmartin/inline_svg/issues/87)
|
75
|
+
Thanks, [@endorfin](https://github.com/endorfin)
|
76
|
+
|
77
|
+
### Added
|
78
|
+
- Raise error on file not found (if configured)
|
79
|
+
[#93](https://github.com/jamesmartin/inline_svg/issues/93)
|
80
|
+
|
81
|
+
## [1.3.1] - 2017-12-14
|
82
|
+
### Fixed
|
83
|
+
- Allow Ruby < 2.1 to work with `CachedAssetFile`
|
84
|
+
[#80](https://github.com/jamesmartin/inline_svg/pull/80)
|
85
|
+
|
86
|
+
## [1.3.0] - 2017-10-30
|
87
|
+
### Added
|
88
|
+
- Aria hidden attribute
|
89
|
+
[#78](https://github.com/jamesmartin/inline_svg/pull/78)
|
90
|
+
and [#79](https://github.com/jamesmartin/inline_svg/pull/79)
|
91
|
+
- In-line CSS style attribute
|
92
|
+
[#71](https://github.com/jamesmartin/inline_svg/pull/71)
|
93
|
+
|
94
|
+
### Fixed
|
95
|
+
- Make aria ID attributes unique
|
96
|
+
[#77](https://github.com/jamesmartin/inline_svg/pull/77)
|
97
|
+
|
98
|
+
## [1.2.3] - 2017-08-17
|
99
|
+
### Fixed
|
100
|
+
- Handle UTF-8 characters in SVG documents
|
101
|
+
[#60](https://github.com/jamesmartin/inline_svg/pull/69)
|
102
|
+
|
103
|
+
## [1.2.2] - 2017-07-06
|
104
|
+
### Fixed
|
105
|
+
- Handle malformed documents that don't contain a root SVG element
|
106
|
+
[#60](https://github.com/jamesmartin/inline_svg/pull/65)
|
107
|
+
### Added
|
108
|
+
- Add configurable CSS class to empty SVG document
|
109
|
+
[#67](https://github.com/jamesmartin/inline_svg/pull/67)
|
110
|
+
|
111
|
+
## [1.2.1] - 2017-05-02
|
112
|
+
### Fixed
|
113
|
+
- Select most exactly matching cached asset file when multiple files match
|
114
|
+
given asset name [#64](https://github.com/jamesmartin/inline_svg/pull/64)
|
115
|
+
|
116
|
+
## [1.2.0] - 2017-04-20
|
117
|
+
### Added
|
118
|
+
- Cached asset file (load assets into memory at boot time)
|
119
|
+
[#62](https://github.com/jamesmartin/inline_svg/pull/62)
|
120
|
+
|
121
|
+
## [1.1.0] - 2017-04-12
|
122
|
+
### Added
|
123
|
+
- Allow configurable asset file implementations
|
124
|
+
[#61](https://github.com/jamesmartin/inline_svg/pull/61)
|
125
|
+
|
126
|
+
## [1.0.1] - 2017-04-10
|
127
|
+
### Fixed
|
128
|
+
- Don't override custom asset finders in Railtie
|
7
129
|
|
8
130
|
## [1.0.0] - 2017-04-7
|
9
131
|
### Added
|
@@ -99,7 +221,7 @@ transformations](https://github.com/jamesmartin/inline_svg/blob/master/README.md
|
|
99
221
|
|
100
222
|
## [0.5.1] - 2015-03-30
|
101
223
|
### Warning
|
102
|
-
** This version is NOT
|
224
|
+
** This version is NOT compatible with Sprockets >= 3. **
|
103
225
|
|
104
226
|
### Fixed
|
105
227
|
- Support for ActiveSupport (and hence, Rails) 4.2.x. Thanks, @jmarceli.
|
@@ -140,7 +262,25 @@ transformations](https://github.com/jamesmartin/inline_svg/blob/master/README.md
|
|
140
262
|
### Added
|
141
263
|
- Basic Railtie and view helper to inline SVG documents to Rails views.
|
142
264
|
|
143
|
-
[unreleased]: https://github.com/jamesmartin/inline_svg/compare/v1.
|
265
|
+
[unreleased]: https://github.com/jamesmartin/inline_svg/compare/v1.9.0...HEAD
|
266
|
+
[1.9.0]: https://github.com/jamesmartin/inline_svg/compare/v1.8.0...v1.9.0
|
267
|
+
[1.8.0]: https://github.com/jamesmartin/inline_svg/compare/v1.7.2...v1.8.0
|
268
|
+
[1.7.2]: https://github.com/jamesmartin/inline_svg/compare/v1.7.1...v1.7.2
|
269
|
+
[1.7.1]: https://github.com/jamesmartin/inline_svg/compare/v1.7.0...v1.7.1
|
270
|
+
[1.7.0]: https://github.com/jamesmartin/inline_svg/compare/v1.6.0...v1.7.0
|
271
|
+
[1.6.0]: https://github.com/jamesmartin/inline_svg/compare/v1.5.2...v1.6.0
|
272
|
+
[1.5.2]: https://github.com/jamesmartin/inline_svg/compare/v1.5.1...v1.5.2
|
273
|
+
[1.5.1]: https://github.com/jamesmartin/inline_svg/compare/v1.5.0...v1.5.1
|
274
|
+
[1.5.0]: https://github.com/jamesmartin/inline_svg/compare/v1.4.0...v1.5.0
|
275
|
+
[1.4.0]: https://github.com/jamesmartin/inline_svg/compare/v1.3.1...v1.4.0
|
276
|
+
[1.3.1]: https://github.com/jamesmartin/inline_svg/compare/v1.3.0...v1.3.1
|
277
|
+
[1.3.0]: https://github.com/jamesmartin/inline_svg/compare/v1.2.3...v1.3.0
|
278
|
+
[1.2.3]: https://github.com/jamesmartin/inline_svg/compare/v1.2.2...v1.2.3
|
279
|
+
[1.2.2]: https://github.com/jamesmartin/inline_svg/compare/v1.2.1...v1.2.2
|
280
|
+
[1.2.1]: https://github.com/jamesmartin/inline_svg/compare/v1.2.0...v1.2.1
|
281
|
+
[1.2.0]: https://github.com/jamesmartin/inline_svg/compare/v1.1.0...v1.2.0
|
282
|
+
[1.1.0]: https://github.com/jamesmartin/inline_svg/compare/v1.0.1...v1.1.0
|
283
|
+
[1.0.1]: https://github.com/jamesmartin/inline_svg/compare/v1.0.0...v1.0.1
|
144
284
|
[1.0.0]: https://github.com/jamesmartin/inline_svg/compare/v0.12.1...v1.0.0
|
145
285
|
[0.12.1]: https://github.com/jamesmartin/inline_svg/compare/v0.12.0...v0.12.1
|
146
286
|
[0.12.0]: https://github.com/jamesmartin/inline_svg/compare/v0.11.1...v0.12.0
|
data/README.md
CHANGED
@@ -1,13 +1,22 @@
|
|
1
1
|
# Inline SVG
|
2
2
|
|
3
|
+

|
4
|
+

|
5
|
+
|
3
6
|
Styling a SVG document with CSS for use on the web is most reliably achieved by
|
4
7
|
[adding classes to the document and
|
5
8
|
embedding](http://css-tricks.com/using-svg/) it inline in the HTML.
|
6
9
|
|
7
|
-
This gem adds
|
10
|
+
This gem adds Rails helper methods (`inline_svg_tag` and `inline_svg_pack_tag`) that read an SVG document (via Sprockets or Webpacker, so works with the Rails Asset Pipeline), applies a CSS class attribute to the root of the document and
|
8
11
|
then embeds it into a view.
|
9
12
|
|
10
|
-
Inline SVG supports
|
13
|
+
Inline SVG supports:
|
14
|
+
|
15
|
+
- [Rails 5](http://weblog.rubyonrails.org/2016/6/30/Rails-5-0-final/) (from [v0.10.0](https://github.com/jamesmartin/inline_svg/releases/tag/v0.10.0))
|
16
|
+
- [Rails 6](https://weblog.rubyonrails.org/2019/4/24/Rails-6-0-rc1-released/) with Sprockets or Webpacker (from [v1.5.2](https://github.com/jamesmartin/inline_svg/releases/tag/v1.5.2)).
|
17
|
+
- [Rails 7](https://weblog.rubyonrails.org/2021/12/6/Rails-7-0-rc-1-released/)
|
18
|
+
|
19
|
+
Inline SVG no longer officially supports Rails 3 or Rails 4 (although they may still work). In order to reduce the maintenance cost of this project we now follow the [Rails Maintenance Policy](https://guides.rubyonrails.org/maintenance_policy.html).
|
11
20
|
|
12
21
|
## Changelog
|
13
22
|
|
@@ -30,9 +39,15 @@ Or install it yourself as:
|
|
30
39
|
|
31
40
|
## Usage
|
32
41
|
|
42
|
+
```ruby
|
43
|
+
# Sprockets
|
44
|
+
inline_svg_tag(file_name, options={})
|
45
|
+
|
46
|
+
# Webpacker
|
47
|
+
inline_svg_pack_tag(file_name, options={})
|
33
48
|
```
|
34
|
-
|
35
|
-
|
49
|
+
|
50
|
+
_**Note:** The remainder of this README uses `inline_svg_tag` for examples, but the exact same principles work for `inline_svg_pack_tag`._
|
36
51
|
|
37
52
|
The `file_name` can be a full path to a file, the file's basename or an `IO`
|
38
53
|
object. The
|
@@ -40,18 +55,20 @@ actual path of the file on disk is resolved using
|
|
40
55
|
[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
56
|
This means you can pre-process and fingerprint your SVG files like other Rails assets, or choose to find SVG data yourself.
|
42
57
|
|
43
|
-
Here's an example of embedding an SVG document and applying a 'class' attribute
|
44
|
-
HAML:
|
58
|
+
Here's an example of embedding an SVG document and applying a 'class' attribute:
|
45
59
|
|
46
|
-
```
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
60
|
+
```erb
|
61
|
+
<html>
|
62
|
+
<head>
|
63
|
+
<title>Embedded SVG Documents<title>
|
64
|
+
</head>
|
65
|
+
<body>
|
66
|
+
<h1>Embedded SVG Documents</h1>
|
67
|
+
<div>
|
68
|
+
<%= inline_svg_tag "some-document.svg", class: 'some-class' %>
|
69
|
+
</div>
|
70
|
+
</body>
|
71
|
+
</html>
|
55
72
|
```
|
56
73
|
|
57
74
|
Here's some CSS to target the SVG, resize it and turn it an attractive shade of
|
@@ -67,30 +84,47 @@ blue:
|
|
67
84
|
}
|
68
85
|
```
|
69
86
|
|
70
|
-
## Options
|
87
|
+
## Options
|
71
88
|
|
72
89
|
key | description
|
73
|
-
:---------------------- | :----------
|
90
|
+
:---------------------- | :----------
|
74
91
|
`id` | set a ID attribute on the SVG
|
75
92
|
`class` | set a CSS class attribute on the SVG
|
93
|
+
`style` | set a CSS style attribute on the SVG
|
76
94
|
`data` | add data attributes to the SVG (supply as a hash)
|
77
95
|
`size` | set width and height attributes on the SVG <br/> Can also be set using `height` and/or `width` attributes, which take precedence over `size` <br/> Supplied as "{Width} * {Height}" or "{Number}", so "30px\*45px" becomes `width="30px"` and `height="45px"`, and "50%" becomes `width="50%"` and `height="50%"`
|
78
96
|
`title` | add a \<title\> node inside the top level of the SVG document
|
79
97
|
`desc` | add a \<desc\> node inside the top level of the SVG document
|
80
98
|
`nocomment` | remove comment tags from the SVG document
|
81
99
|
`preserve_aspect_ratio` | adds a `preserveAspectRatio` attribute to the SVG
|
100
|
+
`view_box` | adds a `viewBox` attribute to the SVG
|
82
101
|
`aria` | adds common accessibility attributes to the SVG (see [PR #34](https://github.com/jamesmartin/inline_svg/pull/34#issue-152062674) for details)
|
102
|
+
`aria_hidden` | adds the `aria-hidden=true` attribute to the SVG
|
103
|
+
`fallback` | set fallback SVG document
|
83
104
|
|
84
105
|
Example:
|
85
106
|
|
86
107
|
```ruby
|
87
|
-
|
88
|
-
|
108
|
+
inline_svg_tag(
|
109
|
+
"some-document.svg",
|
110
|
+
id: 'some-id',
|
111
|
+
class: 'some-class',
|
112
|
+
data: {some: "value"},
|
113
|
+
size: '30% * 20%',
|
114
|
+
title: 'Some Title',
|
115
|
+
desc: 'Some description',
|
116
|
+
nocomment: true,
|
117
|
+
preserve_aspect_ratio: 'xMaxYMax meet',
|
118
|
+
view_box: '0 0 100 100',
|
119
|
+
aria: true,
|
120
|
+
aria_hidden: true,
|
121
|
+
fallback: 'fallback-document.svg'
|
122
|
+
)
|
89
123
|
```
|
90
124
|
|
91
125
|
## Accessibility
|
92
126
|
|
93
|
-
Use the `aria: true` option to make `
|
127
|
+
Use the `aria: true` option to make `inline_svg_tag` add the following
|
94
128
|
accessibility (a11y) attributes to your embedded SVG:
|
95
129
|
|
96
130
|
* Adds a `role="img"` attribute to the root SVG element
|
@@ -101,7 +135,7 @@ Here's an example:
|
|
101
135
|
|
102
136
|
```erb
|
103
137
|
<%=
|
104
|
-
|
138
|
+
inline_svg_tag('iconmonstr-glasses-12-icon.svg',
|
105
139
|
aria: true, title: 'An SVG',
|
106
140
|
desc: 'This is my SVG. There are many like it. You get the picture')
|
107
141
|
%>
|
@@ -115,11 +149,11 @@ Here's an example:
|
|
115
149
|
</svg>
|
116
150
|
```
|
117
151
|
|
118
|
-
***Note:*** The title and desc `id` attributes generated for, and referenced by, `aria-labelled-by` are one-way digests based on the value of the title and desc elements and an optional "salt" value using the SHA1 algorithm. This reduces the chance of `
|
152
|
+
***Note:*** The title and desc `id` attributes generated for, and referenced by, `aria-labelled-by` are one-way digests based on the value of the title and desc elements and an optional "salt" value using the SHA1 algorithm. This reduces the chance of `inline_svg_tag` embedding elements inside the SVG with `id` attributes that clash with other elements elsewhere on the page.
|
119
153
|
|
120
154
|
## Custom Transformations
|
121
155
|
|
122
|
-
The transformation behavior of `
|
156
|
+
The transformation behavior of `inline_svg_tag` can be customized by creating custom transformation classes.
|
123
157
|
|
124
158
|
For example, inherit from `InlineSvg::CustomTransformation` and implement the `#transform` method:
|
125
159
|
|
@@ -129,10 +163,9 @@ For example, inherit from `InlineSvg::CustomTransformation` and implement the `#
|
|
129
163
|
|
130
164
|
class MyCustomTransform < InlineSvg::CustomTransformation
|
131
165
|
def transform(doc)
|
132
|
-
doc
|
133
|
-
|
134
|
-
|
135
|
-
doc
|
166
|
+
with_svg(doc) do |svg|
|
167
|
+
svg["custom"] = value
|
168
|
+
end
|
136
169
|
end
|
137
170
|
end
|
138
171
|
```
|
@@ -149,7 +182,7 @@ end
|
|
149
182
|
The custom transformation can then be called like so:
|
150
183
|
```haml
|
151
184
|
%div
|
152
|
-
=
|
185
|
+
= inline_svg_tag "some-document.svg", my_custom_attribute: 'some value'
|
153
186
|
```
|
154
187
|
|
155
188
|
In this example, the following transformation would be applied to a SVG document:
|
@@ -170,8 +203,8 @@ end
|
|
170
203
|
The custom transformation will be triggered even if you don't pass any attribute value
|
171
204
|
```haml
|
172
205
|
%div
|
173
|
-
=
|
174
|
-
=
|
206
|
+
= inline_svg_tag "some-document.svg"
|
207
|
+
= inline_svg_tag "some-document.svg", my_custom_attribute: 'some value'
|
175
208
|
```
|
176
209
|
|
177
210
|
In this example, the following transformation would be applied to a SVG document:
|
@@ -201,6 +234,92 @@ Transforms are applied in ascending order (lowest number first).
|
|
201
234
|
***Note***: Custom transformations are always applied *after* all built-in
|
202
235
|
transformations, regardless of priority.
|
203
236
|
|
237
|
+
## Custom asset file loader
|
238
|
+
|
239
|
+
An asset file loader returns a `String` representing a SVG document given a
|
240
|
+
filename. Custom asset loaders should be a Ruby object that responds to a
|
241
|
+
method called `named`, that takes one argument (a string representing the
|
242
|
+
filename of the SVG document).
|
243
|
+
|
244
|
+
A simple example might look like this:
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
class MyAssetFileLoader
|
248
|
+
def self.named(filename)
|
249
|
+
# ... load SVG document however you like
|
250
|
+
return "<svg>some document</svg>"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
```
|
254
|
+
|
255
|
+
Configure your custom asset file loader in an initializer like so:
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
InlineSvg.configure do |config|
|
259
|
+
config.asset_file = MyAssetFileLoader
|
260
|
+
end
|
261
|
+
```
|
262
|
+
|
263
|
+
## Caching all assets at boot time
|
264
|
+
|
265
|
+
When your deployment strategy prevents dynamic asset file loading from disk it
|
266
|
+
can be helpful to cache all possible SVG assets in memory at application boot
|
267
|
+
time. In this case, you can configure the `InlineSvg::CachedAssetFile` to scan
|
268
|
+
any number of paths on disks and load all the assets it finds into memory.
|
269
|
+
|
270
|
+
For example, in this configuration we load every `*.svg` file found beneath the
|
271
|
+
configured paths into memory:
|
272
|
+
|
273
|
+
```ruby
|
274
|
+
InlineSvg.configure do |config|
|
275
|
+
config.asset_file = InlineSvg::CachedAssetFile.new(
|
276
|
+
paths: [
|
277
|
+
"#{Rails.root}/public/path/to/assets",
|
278
|
+
"#{Rails.root}/public/other/path/to/assets"
|
279
|
+
],
|
280
|
+
filters: /\.svg/
|
281
|
+
)
|
282
|
+
end
|
283
|
+
```
|
284
|
+
|
285
|
+
**Note:** Paths are read recursively, so think about keeping your SVG assets
|
286
|
+
restricted to as few paths as possible, and using the filter option to further
|
287
|
+
restrict assets to only those likely to be used by `inline_svg_tag`.
|
288
|
+
|
289
|
+
## Missing SVG Files
|
290
|
+
|
291
|
+
If the specified SVG file cannot be found a helpful, empty SVG document is
|
292
|
+
embedded into the page instead. The embedded document contains a single comment
|
293
|
+
displaying the filename of the SVG image the helper tried to render:
|
294
|
+
|
295
|
+
```html
|
296
|
+
<svg><!-- SVG file not found: 'some-missing-file.svg' --></svg>
|
297
|
+
```
|
298
|
+
|
299
|
+
You may apply a class to this empty SVG document by specifying the following
|
300
|
+
configuration:
|
301
|
+
|
302
|
+
```rb
|
303
|
+
InlineSvg.configure do |config|
|
304
|
+
config.svg_not_found_css_class = 'svg-not-found'
|
305
|
+
end
|
306
|
+
```
|
307
|
+
|
308
|
+
Which would instead render:
|
309
|
+
|
310
|
+
```html
|
311
|
+
<svg class='svg-not-found'><!-- SVG file not found: 'some-missing-file.svg' --></svg>
|
312
|
+
```
|
313
|
+
|
314
|
+
Alternatively, `inline_svg_tag` can be configured to raise an exception when a file
|
315
|
+
is not found:
|
316
|
+
|
317
|
+
```ruby
|
318
|
+
InlineSvg.configure do |config|
|
319
|
+
config.raise_on_file_not_found = true
|
320
|
+
end
|
321
|
+
```
|
322
|
+
|
204
323
|
## Contributing
|
205
324
|
|
206
325
|
1. Fork it ( [http://github.com/jamesmartin/inline_svg/fork](http://github.com/jamesmartin/inline_svg/fork) )
|
data/Rakefile
CHANGED
data/inline_svg.gemspec
CHANGED
@@ -18,11 +18,12 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency "bundler", "~>
|
21
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_development_dependency "rspec", "~> 3.2"
|
24
24
|
spec.add_development_dependency "rspec_junit_formatter", "0.2.2"
|
25
25
|
spec.add_development_dependency "pry"
|
26
|
+
spec.add_development_dependency "rubocop"
|
26
27
|
|
27
28
|
spec.add_runtime_dependency "activesupport", ">= 3.0"
|
28
29
|
spec.add_runtime_dependency "nokogiri", ">= 1.6"
|
@@ -4,21 +4,82 @@ require 'action_view/context' if defined?(Rails)
|
|
4
4
|
module InlineSvg
|
5
5
|
module ActionView
|
6
6
|
module Helpers
|
7
|
+
def inline_svg_tag(filename, transform_params={})
|
8
|
+
with_asset_finder(InlineSvg.configuration.asset_finder) do
|
9
|
+
render_inline_svg(filename, transform_params)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def inline_svg_pack_tag(filename, transform_params={})
|
14
|
+
with_asset_finder(InlineSvg::WebpackAssetFinder) do
|
15
|
+
render_inline_svg(filename, transform_params)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
7
19
|
def inline_svg(filename, transform_params={})
|
20
|
+
render_inline_svg(filename, transform_params)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def backwards_compatible_html_escape(filename)
|
26
|
+
# html_escape_once was introduced in newer versions of Rails.
|
27
|
+
if ERB::Util.respond_to?(:html_escape_once)
|
28
|
+
ERB::Util.html_escape_once(filename)
|
29
|
+
else
|
30
|
+
ERB::Util.html_escape(filename)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def render_inline_svg(filename, transform_params={})
|
8
35
|
begin
|
9
|
-
svg_file =
|
10
|
-
|
11
|
-
|
12
|
-
|
36
|
+
svg_file = read_svg(filename)
|
37
|
+
rescue InlineSvg::AssetFile::FileNotFound => error
|
38
|
+
raise error if InlineSvg.configuration.raise_on_file_not_found?
|
39
|
+
return placeholder(filename) unless transform_params[:fallback].present?
|
40
|
+
|
41
|
+
if transform_params[:fallback].present?
|
42
|
+
begin
|
43
|
+
svg_file = read_svg(transform_params[:fallback])
|
44
|
+
rescue InlineSvg::AssetFile::FileNotFound
|
45
|
+
placeholder(filename)
|
46
|
+
end
|
13
47
|
end
|
14
|
-
rescue InlineSvg::AssetFile::FileNotFound
|
15
|
-
return "<svg><!-- SVG file not found: '#{filename}' #{extension_hint(filename)}--></svg>".html_safe
|
16
48
|
end
|
17
49
|
|
18
50
|
InlineSvg::TransformPipeline.generate_html_from(svg_file, transform_params).html_safe
|
19
51
|
end
|
20
52
|
|
21
|
-
|
53
|
+
def read_svg(filename)
|
54
|
+
if InlineSvg::IOResource === filename
|
55
|
+
InlineSvg::IOResource.read filename
|
56
|
+
else
|
57
|
+
configured_asset_file.named filename
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def placeholder(filename)
|
62
|
+
css_class = InlineSvg.configuration.svg_not_found_css_class
|
63
|
+
not_found_message = "'#{backwards_compatible_html_escape(filename)}' #{extension_hint(filename)}"
|
64
|
+
|
65
|
+
if css_class.nil?
|
66
|
+
return "<svg><!-- SVG file not found: #{not_found_message}--></svg>".html_safe
|
67
|
+
else
|
68
|
+
return "<svg class='#{css_class}'><!-- SVG file not found: #{not_found_message}--></svg>".html_safe
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def configured_asset_file
|
73
|
+
InlineSvg.configuration.asset_file
|
74
|
+
end
|
75
|
+
|
76
|
+
def with_asset_finder(asset_finder)
|
77
|
+
Thread.current[:inline_svg_asset_finder] = asset_finder
|
78
|
+
output = yield
|
79
|
+
Thread.current[:inline_svg_asset_finder] = nil
|
80
|
+
|
81
|
+
output
|
82
|
+
end
|
22
83
|
|
23
84
|
def extension_hint(filename)
|
24
85
|
filename.ends_with?(".svg") ? "" : "(Try adding .svg to your filename) "
|
@@ -0,0 +1,71 @@
|
|
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
|
+
@sorted_asset_keys = assets.keys.sort { |a, b| a.size <=> b.size }
|
22
|
+
end
|
23
|
+
|
24
|
+
# Public: Finds the named asset and returns the contents as a string.
|
25
|
+
#
|
26
|
+
# asset_name - A string representing the name of the asset to load
|
27
|
+
#
|
28
|
+
# Returns: A String or raises InlineSvg::AssetFile::FileNotFound error
|
29
|
+
def named(asset_name)
|
30
|
+
assets[key_for_asset(asset_name)] or
|
31
|
+
raise InlineSvg::AssetFile::FileNotFound.new("Asset not found: #{asset_name}")
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
# Internal: Finds the key for a given asset name (using a Regex). In the
|
36
|
+
# event of an ambiguous asset_name matching multiple assets, this method
|
37
|
+
# ranks the matches by their full file path, choosing the shortest (most
|
38
|
+
# exact) match over all others.
|
39
|
+
#
|
40
|
+
# Returns a String representing the key for the named asset or nil if there
|
41
|
+
# is no match.
|
42
|
+
def key_for_asset(asset_name)
|
43
|
+
@sorted_asset_keys.find { |k| k.include?(asset_name) }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Internal: Recursively descends through current_paths reading each file it
|
47
|
+
# finds and adding them to the accumulator if the fullpath of the file
|
48
|
+
# matches all configured filters.
|
49
|
+
#
|
50
|
+
# acc - Hash representing the accumulated assets keyed by full path
|
51
|
+
# paths - Pathname representing the current node in the directory
|
52
|
+
# structure to consider
|
53
|
+
#
|
54
|
+
# Returns a Hash containing the contents of each asset, keyed by fullpath
|
55
|
+
# to the asset.
|
56
|
+
def read_assets(acc, paths)
|
57
|
+
paths.each_child do |child|
|
58
|
+
if child.directory?
|
59
|
+
read_assets(acc, child)
|
60
|
+
elsif child.readable_real?
|
61
|
+
acc[child.to_s] = File.read(child) if matches_all_filters?(child)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
acc
|
65
|
+
end
|
66
|
+
|
67
|
+
def matches_all_filters?(path)
|
68
|
+
filters.all? { |f| f.match(path.to_s) }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -1,8 +1,17 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
1
3
|
module InlineSvg
|
2
4
|
class IdGenerator
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
class Randomness
|
6
|
+
require "securerandom"
|
7
|
+
def self.call
|
8
|
+
SecureRandom.hex(10)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.generate(base, salt, randomness: Randomness)
|
13
|
+
bytes = Digest::SHA1.digest("#{base}-#{salt}-#{randomness.call}")
|
14
|
+
'a' + Digest.hexencode(bytes).to_i(16).to_s(36)
|
6
15
|
end
|
7
16
|
end
|
8
17
|
end
|