Skip to content

Commit

Permalink
Merge pull request #103 from kylefox/finder-helpers
Browse files Browse the repository at this point in the history
Support both Sprockets and Webpacker
  • Loading branch information
jamesmartin authored Nov 13, 2019
2 parents e31b68e + 0ea7099 commit 4d4baa9
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 48 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ rvm:
- 2.4
- 2.5
before_install:
- gem install -v 2.0.1 bundler --no-rdoc --no-ri
- gem install -v 2.0.1 bundler --no-document
script: bundle exec rspec
46 changes: 20 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Styling a SVG document with CSS for use on the web is most reliably achieved by
[adding classes to the document and
embedding](http://css-tricks.com/using-svg/) it inline in the HTML.

This gem adds a Rails helper method (`inline_svg`) that reads 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
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
then embeds it into a view.

Inline SVG supports:
Expand All @@ -16,18 +16,6 @@ Inline SVG supports:
- [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))
- [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)).

## Webpacker


Webpacker support is currently "opt-in" and must be manually configured like
so:

```ruby
InlineSvg.configure do |config|
config.asset_finder = InlineSvg::WebpackAssetFinder
end
```

## Changelog

This project adheres to [Semantic Versioning](http://semver.org). All notable changes are documented in the
Expand All @@ -49,9 +37,15 @@ Or install it yourself as:

## Usage

```ruby
# Sprockets
inline_svg_tag(file_name, options={})

# Webpacker
inline_svg_pack_tag(file_name, options={})
```
inline_svg(file_name, options={})
```

_**Note:** The remainder of this README uses `inline_svg_tag` for examples, but the exact same principles work for `inline_svg_pack_tag`._

The `file_name` can be a full path to a file, the file's basename or an `IO`
object. The
Expand All @@ -69,7 +63,7 @@ Here's an example of embedding an SVG document and applying a 'class' attribute:
<body>
<h1>Embedded SVG Documents</h1>
<div>
<%= inline_svg "some-document.svg", class: 'some-class' %>
<%= inline_svg_tag "some-document.svg", class: 'some-class' %>
</div>
</body>
</html>
Expand Down Expand Up @@ -107,7 +101,7 @@ key | description
Example:

```ruby
inline_svg(
inline_svg_tag(
"some-document.svg",
id: 'some-id',
class: 'some-class',
Expand All @@ -124,7 +118,7 @@ inline_svg(

## Accessibility

Use the `aria: true` option to make `inline_svg` add the following
Use the `aria: true` option to make `inline_svg_tag` add the following
accessibility (a11y) attributes to your embedded SVG:

* Adds a `role="img"` attribute to the root SVG element
Expand All @@ -135,7 +129,7 @@ Here's an example:

```erb
<%=
inline_svg('iconmonstr-glasses-12-icon.svg',
inline_svg_tag('iconmonstr-glasses-12-icon.svg',
aria: true, title: 'An SVG',
desc: 'This is my SVG. There are many like it. You get the picture')
%>
Expand All @@ -149,11 +143,11 @@ Here's an example:
</svg>
```

***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` embedding elements inside the SVG with `id` attributes that clash with other elements elsewhere on the page.
***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.

## Custom Transformations

The transformation behavior of `inline_svg` can be customized by creating custom transformation classes.
The transformation behavior of `inline_svg_tag` can be customized by creating custom transformation classes.

For example, inherit from `InlineSvg::CustomTransformation` and implement the `#transform` method:

Expand Down Expand Up @@ -182,7 +176,7 @@ end
The custom transformation can then be called like so:
```haml
%div
= inline_svg "some-document.svg", my_custom_attribute: 'some value'
= inline_svg_tag "some-document.svg", my_custom_attribute: 'some value'
```

In this example, the following transformation would be applied to a SVG document:
Expand All @@ -203,8 +197,8 @@ end
The custom transformation will be triggered even if you don't pass any attribute value
```haml
%div
= inline_svg "some-document.svg"
= inline_svg "some-document.svg", my_custom_attribute: 'some value'
= inline_svg_tag "some-document.svg"
= inline_svg_tag "some-document.svg", my_custom_attribute: 'some value'
```

In this example, the following transformation would be applied to a SVG document:
Expand Down Expand Up @@ -284,7 +278,7 @@ end

**Note:** Paths are read recursively, so think about keeping your SVG assets
restricted to as few paths as possible, and using the filter option to further
restrict assets to only those likely to be used by `inline_svg`.
restrict assets to only those likely to be used by `inline_svg_tag`.

## Missing SVG Files

Expand All @@ -311,7 +305,7 @@ Which would instead render:
<svg class='svg-not-found'><!-- SVG file not found: 'some-missing-file.svg' --></svg>
```

Alternatively, `inline_svg` can be configured to raise an exception when a file
Alternatively, `inline_svg_tag` can be configured to raise an exception when a file
is not found:

```ruby
Expand Down
34 changes: 32 additions & 2 deletions lib/inline_svg/action_view/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,29 @@
module InlineSvg
module ActionView
module Helpers
def inline_svg_tag(filename, transform_params={})
with_asset_finder(InlineSvg.configuration.asset_finder) do
render_inline_svg(filename, transform_params)
end
end

def inline_svg_pack_tag(filename, transform_params={})
with_asset_finder(InlineSvg::WebpackAssetFinder) do
render_inline_svg(filename, transform_params)
end
end

def inline_svg(filename, transform_params={})
ActiveSupport::Deprecation.warn(
'`inline_svg` is deprecated and will be removed from inline_svg 2.0 (use `inline_svg_tag` or `inline_svg_pack_tag` instead)'
)

render_inline_svg(filename, transform_params)
end

private

def render_inline_svg(filename, transform_params={})
begin
svg_file = read_svg(filename)
rescue InlineSvg::AssetFile::FileNotFound => error
Expand All @@ -23,8 +45,6 @@ def inline_svg(filename, transform_params={})
InlineSvg::TransformPipeline.generate_html_from(svg_file, transform_params).html_safe
end

private

def read_svg(filename)
if InlineSvg::IOResource === filename
InlineSvg::IOResource.read filename
Expand All @@ -48,6 +68,16 @@ def configured_asset_file
InlineSvg.configuration.asset_file
end

def with_asset_finder(asset_finder)
initial_asset_finder = InlineSvg.configuration.asset_finder

InlineSvg.configuration.asset_finder = asset_finder
output = yield
InlineSvg.configuration.asset_finder = initial_asset_finder

output
end

def extension_hint(filename)
filename.ends_with?(".svg") ? "" : "(Try adding .svg to your filename) "
end
Expand Down
50 changes: 31 additions & 19 deletions spec/helpers/inline_svg_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def transform(doc)

let(:helper) { ( Class.new { include InlineSvg::ActionView::Helpers } ).new }

describe "#inline_svg" do
shared_examples "inline_svg helper" do |helper_method:|

context "when passed the name of an SVG that does not exist" do
after(:each) do
Expand All @@ -31,7 +31,7 @@ def transform(doc)
and_raise(InlineSvg::AssetFile::FileNotFound.new)

expect {
helper.inline_svg('some-missing-file.svg')
helper.send(helper_method, 'some-missing-file.svg')
}.to raise_error(InlineSvg::AssetFile::FileNotFound)
end
end
Expand All @@ -41,7 +41,7 @@ def transform(doc)
with('some-missing-file.svg').
and_raise(InlineSvg::AssetFile::FileNotFound.new)

output = helper.inline_svg('some-missing-file.svg')
output = helper.send(helper_method, 'some-missing-file.svg')
expect(output).to eq "<svg><!-- SVG file not found: 'some-missing-file.svg' --></svg>"
expect(output).to be_html_safe
end
Expand All @@ -51,7 +51,7 @@ def transform(doc)
with('missing-file-with-no-extension').
and_raise(InlineSvg::AssetFile::FileNotFound.new)

output = helper.inline_svg('missing-file-with-no-extension')
output = helper.send(helper_method, 'missing-file-with-no-extension')
expect(output).to eq "<svg><!-- SVG file not found: 'missing-file-with-no-extension' (Try adding .svg to your filename) --></svg>"
end

Expand All @@ -64,7 +64,7 @@ def transform(doc)
with('some-other-missing-file.svg').
and_raise(InlineSvg::AssetFile::FileNotFound.new)

output = helper.inline_svg('some-other-missing-file.svg')
output = helper.send(helper_method, 'some-other-missing-file.svg')
expect(output).to eq "<svg class='missing-svg'><!-- SVG file not found: 'some-other-missing-file.svg' --></svg>"
expect(output).to be_html_safe
end
Expand All @@ -79,7 +79,7 @@ def transform(doc)
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="en"><!-- This is a comment --></svg>
SVG
allow(InlineSvg::AssetFile).to receive(:named).with('fallback.svg').and_return(fallback_file)
expect(helper.inline_svg('missing.svg', fallback: 'fallback.svg')).to eq fallback_file
expect(helper.send(helper_method, 'missing.svg', fallback: 'fallback.svg')).to eq fallback_file
end
end
end
Expand All @@ -92,7 +92,7 @@ def transform(doc)
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="en"><!-- This is a comment --></svg>
SVG
allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(example_file)
expect(helper.inline_svg('some-file')).to eq example_file
expect(helper.send(helper_method, 'some-file')).to eq example_file
end
end

Expand All @@ -105,7 +105,7 @@ def transform(doc)
<svg xmlns="http://www.w3.org/2000/svg" role="presentation" xml:lang="en"><title>A title</title></svg>
SVG
allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg)
expect(helper.inline_svg('some-file', title: 'A title')).to eq expected_output
expect(helper.send(helper_method, 'some-file', title: 'A title')).to eq expected_output
end
end

Expand All @@ -118,7 +118,7 @@ def transform(doc)
<svg xmlns="http://www.w3.org/2000/svg" role="presentation" xml:lang="en"><desc>A description</desc></svg>
SVG
allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg)
expect(helper.inline_svg('some-file', desc: 'A description')).to eq expected_output
expect(helper.send(helper_method, 'some-file', desc: 'A description')).to eq expected_output
end
end

Expand All @@ -131,7 +131,7 @@ def transform(doc)
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="en"></svg>
SVG
allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg)
expect(helper.inline_svg('some-file', nocomment: true)).to eq expected_output
expect(helper.send(helper_method, 'some-file', nocomment: true)).to eq expected_output
end
end

Expand All @@ -144,7 +144,7 @@ def transform(doc)
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="en" aria-hidden="true"></svg>
SVG
allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg)
expect(helper.inline_svg('some-file', aria_hidden: true)).to eq expected_output
expect(helper.send(helper_method, 'some-file', aria_hidden: true)).to eq expected_output
end
end

Expand All @@ -157,7 +157,7 @@ def transform(doc)
<svg xmlns="http://www.w3.org/2000/svg" xml:lang="en"><title>A title</title><desc>A description</desc></svg>
SVG
allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg)
expect(helper.inline_svg('some-file', title: 'A title', desc: 'A description', nocomment: true)).to eq expected_output
expect(helper.send(helper_method, 'some-file', title: 'A title', desc: 'A description', nocomment: true)).to eq expected_output
end
end

Expand All @@ -180,7 +180,7 @@ def transform(doc)
<svg custom="some value"></svg>
SVG
allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg)
expect(helper.inline_svg('some-file', custom: 'some value')).to eq expected_output
expect(helper.send(helper_method, 'some-file', custom: 'some value')).to eq expected_output
end
end

Expand All @@ -201,7 +201,7 @@ def transform(doc)

allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg)

expect(helper.inline_svg('some-file')).to eq "<svg custom=\"default value\"></svg>\n"
expect(helper.send(helper_method, 'some-file')).to eq "<svg custom=\"default value\"></svg>\n"
end
end

Expand All @@ -211,7 +211,7 @@ def transform(doc)

allow(InlineSvg::AssetFile).to receive(:named).with('some-file').and_return(input_svg)

expect(helper.inline_svg('some-file', custom: 'some value')).to eq "<svg custom=\"some value\"></svg>\n"
expect(helper.send(helper_method, 'some-file', custom: 'some value')).to eq "<svg custom=\"some value\"></svg>\n"
end
end
end
Expand All @@ -223,13 +223,13 @@ def transform(doc)
expect(InlineSvg::IOResource).to receive(:===).with(argument).and_return(true)
expect(InlineSvg::IOResource).to receive(:read).with(argument)
expect(InlineSvg::AssetFile).to_not receive(:named)
helper.inline_svg(argument)
helper.send(helper_method, argument)
end
it 'accept filename' do
expect(InlineSvg::IOResource).to receive(:===).with(argument).and_return(false)
expect(InlineSvg::IOResource).to_not receive(:read)
expect(InlineSvg::AssetFile).to receive(:named).with(argument)
helper.inline_svg(argument)
helper.send(helper_method, argument)
end
end
context 'when passed IO object argument' do
Expand All @@ -239,17 +239,29 @@ def transform(doc)
it 'return valid svg' do
expect(InlineSvg::IOResource).to receive(:===).with(io_object).and_return(true)
expect(InlineSvg::IOResource).to receive(:read).with(io_object).and_return("<svg><!-- Test IO --></svg>")
output = helper.inline_svg(io_object)
output = helper.send(helper_method, io_object)
expect(output).to eq "<svg><!-- Test IO --></svg>\n"
expect(output).to be_html_safe
end

it 'return valid svg for file' do
output = helper.inline_svg(File.new(file_path))
output = helper.send(helper_method, File.new(file_path))
expect(output).to eq "<svg xmlns=\"http://www.w3.org/2000/svg\" xml:lang=\"en\" role=\"presentation\"><!-- This is a test comment --></svg>\n"
expect(output).to be_html_safe
end

end
end

describe '#inline_svg' do
it_behaves_like "inline_svg helper", helper_method: :inline_svg
end

describe '#inline_svg_tag' do
it_behaves_like "inline_svg helper", helper_method: :inline_svg_tag
end

describe '#inline_svg_tag' do
it_behaves_like "inline_svg helper", helper_method: :inline_svg_pack_tag
end
end

0 comments on commit 4d4baa9

Please sign in to comment.