Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support both Sprockets and Webpacker #103

Merged
merged 6 commits into from
Nov 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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