Add a picture_tag helper
This commit is contained in:
parent
cd100e5338
commit
fac9218f78
@ -1,3 +1,51 @@
|
||||
* Add support for the HTML picture tag. It supports passing a String, an Array or a Block.
|
||||
Supports passing properties directly to the img tag via the `:image` key.
|
||||
Since the picture tag requires an img tag, the last element you provide will be used for the img tag.
|
||||
For complete control over the picture tag, a block can be passed, which will populate the contents of the tag accordingly.
|
||||
|
||||
Can be used like this for a single source:
|
||||
```erb
|
||||
<%= picture_tag("picture.webp") %>
|
||||
```
|
||||
which will generate the following:
|
||||
```html
|
||||
<picture>
|
||||
<img src="/images/picture.webp" />
|
||||
</picture>
|
||||
```
|
||||
|
||||
For multiple sources:
|
||||
```erb
|
||||
<%= picture_tag("picture.webp", "picture.png", :class => "mt-2", :image => { alt: "Image", class: "responsive-img" }) %>
|
||||
```
|
||||
will generate:
|
||||
```html
|
||||
<picture class="mt-2">
|
||||
<source srcset="/images/picture.webp" />
|
||||
<source srcset="/images/picture.png" />
|
||||
<img alt="Image" class="responsive-img" src="/images/picture.png" />
|
||||
</picture>
|
||||
```
|
||||
|
||||
Full control via a block:
|
||||
```erb
|
||||
<%= picture_tag(:class => "my-class") do %>
|
||||
<%= tag(:source, :srcset => image_path("picture.webp")) %>
|
||||
<%= tag(:source, :srcset => image_path("picture.png")) %>
|
||||
<%= image_tag("picture.png", :alt => "Image") %>
|
||||
<% end %>
|
||||
```
|
||||
will generate:
|
||||
```html
|
||||
<picture class="my-class">
|
||||
<source srcset="/images/picture.webp" />
|
||||
<source srcset="/images/picture.png" />
|
||||
<img alt="Image" src="/images/picture.png" />
|
||||
</picture>
|
||||
```
|
||||
|
||||
*Juan Pablo Balarini*
|
||||
|
||||
* Remove deprecated support to passing instance variables as locals to partials.
|
||||
|
||||
*Rafael Mendonça França*
|
||||
|
@ -435,6 +435,63 @@ def image_tag(source, options = {})
|
||||
tag("img", options)
|
||||
end
|
||||
|
||||
# Returns an HTML picture tag for the +sources+. If +sources+ is a string,
|
||||
# a single picture tag will be returned. If +sources+ is an array, a picture
|
||||
# tag with nested source tags for each source will be returned. The
|
||||
# +sources+ can be full paths, files that exist in your public images
|
||||
# directory, or Active Storage attachments. Since the picture tag requires
|
||||
# an img tag, the last element you provide will be used for the img tag.
|
||||
# For complete control over the picture tag, a block can be passed, which
|
||||
# will populate the contents of the tag accordingly.
|
||||
#
|
||||
# ==== Options
|
||||
#
|
||||
# When the last parameter is a hash you can add HTML attributes using that
|
||||
# parameter. Apart from all the HTML supported options, the following are supported:
|
||||
#
|
||||
# * <tt>:image</tt> - Hash of options that are passed directly to the +image_tag+ helper.
|
||||
#
|
||||
# ==== Examples
|
||||
#
|
||||
# picture_tag("picture.webp")
|
||||
# # => <picture><img src="/images/picture.webp" /></picture>
|
||||
# picture_tag("gold.png", :image => { :size => "20" }
|
||||
# # => <picture><img height="20" src="/images/gold.png" width="20" /></picture>
|
||||
# picture_tag("gold.png", :image => { :size => "45x70" })
|
||||
# # => <picture><img height="70" src="/images/gold.png" width="45" /></picture>
|
||||
# picture_tag("picture.webp", "picture.png")
|
||||
# # => <picture><source srcset="/images/picture.webp" /><source srcset="/images/picture.png" /><img src="/images/picture.png" /></picture>
|
||||
# picture_tag("picture.webp", "picture.png", :image => { alt: "Image" })
|
||||
# # => <picture><source srcset="/images/picture.webp" /><source srcset="/images/picture.png" /><img alt="Image" src="/images/picture.png" /></picture>
|
||||
# picture_tag(["picture.webp", "picture.png"], :image => { alt: "Image" })
|
||||
# # => <picture><source srcset="/images/picture.webp" /><source srcset="/images/picture.png" /><img alt="Image" src="/images/picture.png" /></picture>
|
||||
# picture_tag(:class => "my-class") { tag(:source, :srcset => image_path("picture.webp")) + image_tag("picture.png", :alt => "Image") }
|
||||
# # => <picture class="my-class"><source srcset="/images/picture.webp" /><img alt="Image" src="/images/picture.png" /></picture>
|
||||
# picture_tag { tag(:source, :srcset => image_path("picture-small.webp"), :media => "(min-width: 600px)") + tag(:source, :srcset => image_path("picture-big.webp")) + image_tag("picture.png", :alt => "Image") }
|
||||
# # => <picture><source srcset="/images/picture-small.webp" media="(min-width: 600px)" /><source srcset="/images/picture-big.webp" /><img alt="Image" src="/images/picture.png" /></picture>
|
||||
#
|
||||
# Active Storage blobs (images that are uploaded by the users of your app):
|
||||
#
|
||||
# picture_tag(user.profile_picture)
|
||||
# # => <picture><img src="/rails/active_storage/blobs/.../profile_picture.webp" /></picture>
|
||||
def picture_tag(*sources, &block)
|
||||
sources.flatten!
|
||||
options = sources.extract_options!.symbolize_keys
|
||||
picture_options = options.except(:image)
|
||||
image_options = options.fetch(:image, {})
|
||||
skip_pipeline = options.delete(:skip_pipeline)
|
||||
source_tags = []
|
||||
|
||||
content_tag(:picture, picture_options) do
|
||||
if block.present?
|
||||
capture(&block).html_safe
|
||||
else
|
||||
source_tags = sources.map { |source| tag("source", srcset: resolve_asset_source("image", source, skip_pipeline)) } if sources.size > 1
|
||||
safe_join(source_tags << image_tag(sources.last, image_options))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Returns an HTML video tag for the +sources+. If +sources+ is a string,
|
||||
# a single video tag will be returned. If +sources+ is an array, a video
|
||||
# tag with nested source tags for each source will be returned. The
|
||||
|
@ -247,6 +247,68 @@ def content_security_policy_nonce
|
||||
%(image_tag("rss.gif", srcset: [["pic_640.jpg", "640w"], ["pic_1024.jpg", "1024w"]])) => %(<img srcset="/images/pic_640.jpg 640w, /images/pic_1024.jpg 1024w" src="/images/rss.gif" />)
|
||||
}
|
||||
|
||||
PicturePathToTag = {
|
||||
%(image_path("xml")) => %(/images/xml),
|
||||
%(image_path("xml.webp")) => %(/images/xml.webp),
|
||||
%(image_path("dir/xml.webp")) => %(/images/dir/xml.webp),
|
||||
%(image_path("/dir/xml.webp")) => %(/dir/xml.webp)
|
||||
}
|
||||
|
||||
PathToPictureToTag = {
|
||||
%(path_to_image("xml")) => %(/images/xml),
|
||||
%(path_to_image("xml.webp")) => %(/images/xml.webp),
|
||||
%(path_to_image("dir/xml.webp")) => %(/images/dir/xml.webp),
|
||||
%(path_to_image("/dir/xml.webp")) => %(/dir/xml.webp)
|
||||
}
|
||||
|
||||
PictureUrlToTag = {
|
||||
%(image_url("xml")) => %(http://www.example.com/images/xml),
|
||||
%(image_url("xml.webp")) => %(http://www.example.com/images/xml.webp),
|
||||
%(image_url("dir/xml.webp")) => %(http://www.example.com/images/dir/xml.webp),
|
||||
%(image_url("/dir/xml.webp")) => %(http://www.example.com/dir/xml.webp)
|
||||
}
|
||||
|
||||
UrlToPictureToTag = {
|
||||
%(url_to_image("xml")) => %(http://www.example.com/images/xml),
|
||||
%(url_to_image("xml.webp")) => %(http://www.example.com/images/xml.webp),
|
||||
%(url_to_image("dir/xml.webp")) => %(http://www.example.com/images/dir/xml.webp),
|
||||
%(url_to_image("/dir/xml.webp")) => %(http://www.example.com/dir/xml.webp)
|
||||
}
|
||||
|
||||
PictureLinkToTag = {
|
||||
%(picture_tag("picture.webp")) => %(<picture><img src="/images/picture.webp" /></picture>),
|
||||
%(picture_tag("gold.png", :image => { :size => "20" })) => %(<picture><img height="20" src="/images/gold.png" width="20" /></picture>),
|
||||
%(picture_tag("gold.png", :image => { :size => 20 })) => %(<picture><img height="20" src="/images/gold.png" width="20" /></picture>),
|
||||
%(picture_tag("silver.png", :image => { :size => "90.9" })) => %(<picture><img height="90.9" src="/images/silver.png" width="90.9" /></picture>),
|
||||
%(picture_tag("silver.png", :image => { :size => 90.9 })) => %(<picture><img height="90.9" src="/images/silver.png" width="90.9" /></picture>),
|
||||
%(picture_tag("gold.png", :image => { :size => "45x70" })) => %(<picture><img height="70" src="/images/gold.png" width="45" /></picture>),
|
||||
%(picture_tag("gold.png", :image => { "size" => "45x70" })) => %(<picture><img height="70" src="/images/gold.png" width="45" /></picture>),
|
||||
%(picture_tag("silver.png", :image => { :size => "67.12x74.09" })) => %(<picture><img height="74.09" src="/images/silver.png" width="67.12" /></picture>),
|
||||
%(picture_tag("silver.png", :image => { "size" => "67.12x74.09" })) => %(<picture><img height="74.09" src="/images/silver.png" width="67.12" /></picture>),
|
||||
%(picture_tag("bronze.png", :image => { :size => "10x15.7" })) => %(<picture><img height="15.7" src="/images/bronze.png" width="10" /></picture>),
|
||||
%(picture_tag("bronze.png", :image => { "size" => "10x15.7" })) => %(<picture><img height="15.7" src="/images/bronze.png" width="10" /></picture>),
|
||||
%(picture_tag("platinum.png", :image => { :size => "4.9x20" })) => %(<picture><img height="20" src="/images/platinum.png" width="4.9" /></picture>),
|
||||
%(picture_tag("platinum.png", :image => { "size" => "4.9x20" })) => %(<picture><img height="20" src="/images/platinum.png" width="4.9" /></picture>),
|
||||
%(picture_tag("error.png", :image => { "size" => "45 x 70" })) => %(<picture><img src="/images/error.png" /></picture>),
|
||||
%(picture_tag("error.png", :image => { "size" => "1,024x768" })) => %(<picture><img src="/images/error.png" /></picture>),
|
||||
%(picture_tag("error.png", :image => { "size" => "768x1,024" })) => %(<picture><img src="/images/error.png" /></picture>),
|
||||
%(picture_tag("error.png", :image => { "size" => "x" })) => %(<picture><img src="/images/error.png" /></picture>),
|
||||
%(picture_tag("google.com.png")) => %(<picture><img src="/images/google.com.png" /></picture>),
|
||||
%(picture_tag("slash..png")) => %(<picture><img src="/images/slash..png" /></picture>),
|
||||
%(picture_tag(".pdf.png")) => %(<picture><img src="/images/.pdf.png" /></picture>),
|
||||
%(picture_tag("http://www.rubyonrails.com/images/rails.png")) => %(<picture><img src="http://www.rubyonrails.com/images/rails.png" /></picture>),
|
||||
%(picture_tag("//www.rubyonrails.com/images/rails.png")) => %(<picture><img src="//www.rubyonrails.com/images/rails.png" /></picture>),
|
||||
%(picture_tag("mouse.png", :image => { :alt => nil })) => %(<picture><img src="/images/mouse.png" /></picture>),
|
||||
%(picture_tag("data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==", :image => { :alt => nil })) => %(<picture><img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" /></picture>),
|
||||
%(picture_tag("")) => %(<picture><img src="" /></picture>),
|
||||
%(picture_tag("picture.webp", "picture.png")) => %(<picture><source srcset="/images/picture.webp" /><source srcset="/images/picture.png" /><img src="/images/picture.png" /></picture>),
|
||||
%(picture_tag("picture.webp", "picture.png", :class => "my-class")) => %(<picture class="my-class"><source srcset="/images/picture.webp" /><source srcset="/images/picture.png" /><img src="/images/picture.png" /></picture>),
|
||||
%(picture_tag("picture.webp", "picture.png", :image => { alt: "Image" })) => %(<picture><source srcset="/images/picture.webp" /><source srcset="/images/picture.png" /><img alt="Image" src="/images/picture.png" /></picture>),
|
||||
%(picture_tag(["picture.webp", "picture.png"], :image => { alt: "Image" })) => %(<picture><source srcset="/images/picture.webp" /><source srcset="/images/picture.png" /><img alt="Image" src="/images/picture.png" /></picture>),
|
||||
%(picture_tag(:class => "my-class") { tag(:source, :srcset => image_path("picture.webp")) + image_tag("picture.png", :alt => "Image") }) => %(<picture class="my-class"><source srcset="/images/picture.webp" /><img alt="Image" src="/images/picture.png" /></picture>),
|
||||
%(picture_tag { tag(:source, :srcset => image_path("picture-small.webp"), :media => "(min-width: 600px)") + tag(:source, :srcset => image_path("picture-big.webp")) + image_tag("picture.png", :alt => "Image") }) => %(<picture><source srcset="/images/picture-small.webp" media="(min-width: 600px)" /><source srcset="/images/picture-big.webp" /><img alt="Image" src="/images/picture.png" /></picture>),
|
||||
}
|
||||
|
||||
FaviconLinkToTag = {
|
||||
%(favicon_link_tag) => %(<link href="/images/favicon.ico" rel="icon" type="image/x-icon" />),
|
||||
%(favicon_link_tag 'favicon.ico') => %(<link href="/images/favicon.ico" rel="icon" type="image/x-icon" />),
|
||||
@ -711,6 +773,26 @@ def test_preload_link_tag
|
||||
PreloadLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
|
||||
end
|
||||
|
||||
def test_picture_path
|
||||
PicturePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
|
||||
end
|
||||
|
||||
def test_path_to_picture_alias_for_picture_path
|
||||
PathToPictureToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
|
||||
end
|
||||
|
||||
def test_picture_url
|
||||
PictureUrlToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
|
||||
end
|
||||
|
||||
def test_url_to_picture_alias_for_picture_url
|
||||
UrlToPictureToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
|
||||
end
|
||||
|
||||
def test_picture_tag
|
||||
PictureLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
|
||||
end
|
||||
|
||||
def test_video_path
|
||||
VideoPathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user