aboutsummaryrefslogtreecommitdiffstats
path: root/actionview
diff options
context:
space:
mode:
Diffstat (limited to 'actionview')
-rw-r--r--actionview/CHANGELOG.md13
-rw-r--r--actionview/README.rdoc4
-rw-r--r--actionview/RUNNING_UJS_TESTS.rdoc9
-rw-r--r--actionview/RUNNING_UNIT_TESTS.rdoc13
-rw-r--r--actionview/lib/action_view/gem_version.rb2
-rw-r--r--actionview/lib/action_view/helpers/asset_tag_helper.rb79
-rw-r--r--actionview/package.json2
-rw-r--r--actionview/test/template/asset_tag_helper_test.rb45
8 files changed, 150 insertions, 17 deletions
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index c866cdcc33..f42ada0baa 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1,3 +1,16 @@
+* Add `preload_link_tag` helper
+
+ This helper that allows to the browser to initiate early fetch of resources
+ (different to the specified in `javascript_include_tag` and `stylesheet_link_tag`).
+ Additionally, this sends Early Hints if supported by browser.
+
+ *Guillermo Iguaran*
+
+## Rails 5.2.0.beta2 (November 28, 2017) ##
+
+* No changes.
+
+
## Rails 5.2.0.beta1 (November 27, 2017) ##
* Change `form_with` to generates ids by default.
diff --git a/actionview/README.rdoc b/actionview/README.rdoc
index d5029599b7..03a0723564 100644
--- a/actionview/README.rdoc
+++ b/actionview/README.rdoc
@@ -11,7 +11,7 @@ The latest version of Action View can be installed with RubyGems:
$ gem install actionview
-Source code can be downloaded as part of the Rails project on GitHub
+Source code can be downloaded as part of the Rails project on GitHub:
* https://github.com/rails/rails/tree/master/actionview
@@ -29,7 +29,7 @@ API documentation is at
* http://api.rubyonrails.org
-Bug reports can be filed for the Ruby on Rails project here:
+Bug reports for the Ruby on Rails project can be filed here:
* https://github.com/rails/rails/issues
diff --git a/actionview/RUNNING_UJS_TESTS.rdoc b/actionview/RUNNING_UJS_TESTS.rdoc
index a575624a06..e30c2aee55 100644
--- a/actionview/RUNNING_UJS_TESTS.rdoc
+++ b/actionview/RUNNING_UJS_TESTS.rdoc
@@ -1,7 +1,8 @@
== Running UJS tests
-Ensure that you can build the project and run tests.
-Run rake ujs:server first, and then run the web tests by
-visiting http://localhost:4567 in your browser.
+Ensure that you can build the project by running:
+ rake ujs:server
-rake ujs:server
+Then run the web tests by visiting the following URL in your browser:
+
+ http://localhost:4567
diff --git a/actionview/RUNNING_UNIT_TESTS.rdoc b/actionview/RUNNING_UNIT_TESTS.rdoc
index e99d5ca1df..4442dbdb9e 100644
--- a/actionview/RUNNING_UNIT_TESTS.rdoc
+++ b/actionview/RUNNING_UNIT_TESTS.rdoc
@@ -2,13 +2,13 @@
The easiest way to run the unit tests is through Rake. The default task runs
the entire test suite for all classes. For more information, checkout the
-full array of rake tasks with "rake -T"
+full array of rake tasks with <tt>rake -T</tt>
Rake can be found at https://ruby.github.io/rake/.
== Running by hand
-To run a single test suite
+Run a single test suite:
rake test TEST=path/to/test.rb
@@ -18,10 +18,9 @@ which can be further narrowed down to one test:
== Dependency on Active Record and database setup
-Test cases in the test/activerecord/ directory depend on having
-activerecord and sqlite3 installed. If Active Record is not in
-actionview/../activerecord directory, or the sqlite3 rubygem is not installed,
-these tests are skipped.
-
+Test cases in the +test/activerecord/+ directory depend on having
+activerecord+ and +sqlite3+ installed. If Active Record is not in
+actionview/../activerecord+ directory, or the +sqlite3+ Ruby gem is not installed,
+ these tests are skipped.
Other tests are runnable from a fresh copy of actionview without any configuration.
diff --git a/actionview/lib/action_view/gem_version.rb b/actionview/lib/action_view/gem_version.rb
index ef233e23ef..ff7f2bb853 100644
--- a/actionview/lib/action_view/gem_version.rb
+++ b/actionview/lib/action_view/gem_version.rb
@@ -10,7 +10,7 @@ module ActionView
MAJOR = 5
MINOR = 2
TINY = 0
- PRE = "beta1"
+ PRE = "beta2"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
diff --git a/actionview/lib/action_view/helpers/asset_tag_helper.rb b/actionview/lib/action_view/helpers/asset_tag_helper.rb
index e362f13798..da630129cb 100644
--- a/actionview/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionview/lib/action_view/helpers/asset_tag_helper.rb
@@ -2,6 +2,8 @@
require "active_support/core_ext/array/extract_options"
require "active_support/core_ext/hash/keys"
+require "active_support/core_ext/object/inclusion"
+require "active_support/core_ext/object/try"
require "action_view/helpers/asset_url_helper"
require "action_view/helpers/tag_helper"
@@ -91,7 +93,7 @@ module ActionView
content_tag("script".freeze, "", tag_options)
}.join("\n").html_safe
- request.send_early_hints("Link" => early_hints_links.join("\n")) if respond_to?(:request)
+ request.send_early_hints("Link" => early_hints_links.join("\n")) if respond_to?(:request) && request
sources_tags
end
@@ -140,7 +142,7 @@ module ActionView
tag(:link, tag_options)
}.join("\n").html_safe
- request.send_early_hints("Link" => early_hints_links.join("\n")) if respond_to?(:request)
+ request.send_early_hints("Link" => early_hints_links.join("\n")) if respond_to?(:request) && request
sources_tags
end
@@ -221,6 +223,67 @@ module ActionView
}.merge!(options.symbolize_keys))
end
+ # Returns a link tag that browsers can use to preload the +source+.
+ # The +source+ can be the path of an resource managed by asset pipeline,
+ # a full path or an URI.
+ #
+ # ==== Options
+ #
+ # * <tt>:type</tt> - Override the auto-generated mime type, defaults to the mime type for +source+ extension.
+ # * <tt>:as</tt> - Override the auto-generated value for as attribute, calculated using +source+ extension and mime type.
+ # * <tt>:crossorigin</tt> - Specify the crossorigin attribute, required to load cross-origin resources.
+ # * <tt>:nopush</tt> - Specify if the use of server push is not desired for the resource. Defaults to +false+.
+ #
+ # ==== Examples
+ #
+ # preload_link_tag("custom_theme.css")
+ # # => <link rel="preload" href="/assets/custom_theme.css" as="style" type="text/css" />
+ #
+ # preload_link_tag("/videos/video.webm")
+ # # => <link rel="preload" href="/videos/video.mp4" as="video" type="video/webm" />
+ #
+ # preload_link_tag(post_path(format: :json), as: "fetch")
+ # # => <link rel="preload" href="/posts.json" as="fetch" type="application/json" />
+ #
+ # preload_link_tag("worker.js", as: "worker")
+ # # => <link rel="preload" href="/assets/worker.js" as="worker" type="text/javascript" />
+ #
+ # preload_link_tag("//example.com/font.woff2")
+ # # => <link rel="preload" href="//example.com/font.woff2" as="font" type="font/woff2" crossorigin="anonymous"/>
+ #
+ # preload_link_tag("//example.com/font.woff2", crossorigin: "use-credentials")
+ # # => <link rel="preload" href="//example.com/font.woff2" as="font" type="font/woff2" crossorigin="use-credentials" />
+ #
+ # preload_link_tag("/media/audio.ogg", nopush: true)
+ # # => <link rel="preload" href="/media/audio.ogg" as="audio" type="audio/ogg" />
+ #
+ def preload_link_tag(source, options = {})
+ href = asset_path(source, skip_pipeline: options.delete(:skip_pipeline))
+ extname = File.extname(source).downcase.delete(".")
+ mime_type = options.delete(:type) || Template::Types[extname].try(:to_s)
+ as_type = options.delete(:as) || resolve_link_as(extname, mime_type)
+ crossorigin = options.delete(:crossorigin)
+ crossorigin = "anonymous" if crossorigin == true || (crossorigin.blank? && as_type == "font")
+ nopush = options.delete(:nopush) || false
+
+ link_tag = tag.link({
+ rel: "preload",
+ href: href,
+ as: as_type,
+ type: mime_type,
+ crossorigin: crossorigin
+ }.merge!(options.symbolize_keys))
+
+ early_hints_link = "<#{href}>; rel=preload; as=#{as_type}"
+ early_hints_link += "; type=#{mime_type}" if mime_type
+ early_hints_link += "; crossorigin=#{crossorigin}" if crossorigin
+ early_hints_link += "; nopush" if nopush
+
+ request.send_early_hints("Link" => early_hints_link) if respond_to?(:request) && request
+
+ link_tag
+ end
+
# Returns an HTML image tag for the +source+. The +source+ can be a full
# path, a file or an Active Storage attachment.
#
@@ -417,6 +480,18 @@ module ActionView
raise ArgumentError, "Cannot pass a :size option with a :height or :width option"
end
end
+
+ def resolve_link_as(extname, mime_type)
+ if extname == "js"
+ "script"
+ elsif extname == "css"
+ "style"
+ elsif extname == "vtt"
+ "track"
+ elsif (type = mime_type.to_s.split("/")[0]) && type.in?(%w(audio video font))
+ type
+ end
+ end
end
end
end
diff --git a/actionview/package.json b/actionview/package.json
index a8f35ad26f..787ae06208 100644
--- a/actionview/package.json
+++ b/actionview/package.json
@@ -1,6 +1,6 @@
{
"name": "rails-ujs",
- "version": "5.2.0-beta1",
+ "version": "5.2.0-beta2",
"description": "Ruby on Rails unobtrusive scripting adapter",
"main": "lib/assets/compiled/rails-ujs.js",
"files": [
diff --git a/actionview/test/template/asset_tag_helper_test.rb b/actionview/test/template/asset_tag_helper_test.rb
index 7475f5cc3c..284dacf2d4 100644
--- a/actionview/test/template/asset_tag_helper_test.rb
+++ b/actionview/test/template/asset_tag_helper_test.rb
@@ -214,6 +214,17 @@ class AssetTagHelperTest < ActionView::TestCase
%(favicon_link_tag 'mb-icon.png', :rel => 'apple-touch-icon', :type => 'image/png') => %(<link href="/images/mb-icon.png" rel="apple-touch-icon" type="image/png" />)
}
+ PreloadLinkToTag = {
+ %(preload_link_tag '/styles/custom_theme.css') => %(<link rel="preload" href="/styles/custom_theme.css" as="style" type="text/css" />),
+ %(preload_link_tag '/videos/video.webm') => %(<link rel="preload" href="/videos/video.webm" as="video" type="video/webm" />),
+ %(preload_link_tag '/posts.json', as: 'fetch') => %(<link rel="preload" href="/posts.json" as="fetch" type="application/json" />),
+ %(preload_link_tag '/users', as: 'fetch', type: 'application/json') => %(<link rel="preload" href="/users" as="fetch" type="application/json" />),
+ %(preload_link_tag '//example.com/map?callback=initMap', as: 'fetch', type: 'application/javascript') => %(<link rel="preload" href="//example.com/map?callback=initMap" as="fetch" type="application/javascript" />),
+ %(preload_link_tag '//example.com/font.woff2') => %(<link rel="preload" href="//example.com/font.woff2" as="font" type="font/woff2" crossorigin="anonymous"/>),
+ %(preload_link_tag '//example.com/font.woff2', crossorigin: 'use-credentials') => %(<link rel="preload" href="//example.com/font.woff2" as="font" type="font/woff2" crossorigin="use-credentials" />),
+ %(preload_link_tag '/media/audio.ogg', nopush: true) => %(<link rel="preload" href="/media/audio.ogg" as="audio" type="audio/ogg" />)
+ }
+
VideoPathToTag = {
%(video_path("xml")) => %(/videos/xml),
%(video_path("xml.ogg")) => %(/videos/xml.ogg),
@@ -440,6 +451,14 @@ class AssetTagHelperTest < ActionView::TestCase
}
end
+ def test_stylesheet_link_tag_without_request
+ @request = nil
+ assert_dom_equal(
+ %(<link rel="stylesheet" media="screen" href="/stylesheets/foo.css" />),
+ stylesheet_link_tag("foo.css")
+ )
+ end
+
def test_stylesheet_link_tag_is_html_safe
assert stylesheet_link_tag("dir/file").html_safe?
assert stylesheet_link_tag("dir/other/file", "dir/file2").html_safe?
@@ -464,6 +483,11 @@ class AssetTagHelperTest < ActionView::TestCase
assert_dom_equal %(<link href="//assets.example.com/stylesheets/wellington.css" media="screen" rel="stylesheet" />), stylesheet_link_tag("wellington")
end
+ def test_javascript_include_tag_without_request
+ @request = nil
+ assert_dom_equal %(<script src="/javascripts/foo.js"></script>), javascript_include_tag("foo.js")
+ end
+
def test_image_path
ImagePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
@@ -522,6 +546,10 @@ class AssetTagHelperTest < ActionView::TestCase
FaviconLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
+ def test_preload_link_tag
+ PreloadLinkToTag.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
@@ -778,6 +806,23 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase
end
end
+class AssetTagHelperWithoutRequestTest < ActionView::TestCase
+ tests ActionView::Helpers::AssetTagHelper
+
+ undef :request
+
+ def test_stylesheet_link_tag_without_request
+ assert_dom_equal(
+ %(<link rel="stylesheet" media="screen" href="/stylesheets/foo.css" />),
+ stylesheet_link_tag("foo.css")
+ )
+ end
+
+ def test_javascript_include_tag_without_request
+ assert_dom_equal %(<script src="/javascripts/foo.js"></script>), javascript_include_tag("foo.js")
+ end
+end
+
class AssetUrlHelperControllerTest < ActionView::TestCase
tests ActionView::Helpers::AssetUrlHelper