sprockets-rails 2.3.2 → 3.2.2
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/{LICENSE → MIT-LICENSE} +1 -1
- data/README.md +66 -36
- data/lib/sprockets/rails/context.rb +48 -0
- data/lib/sprockets/rails/helper.rb +271 -128
- data/lib/sprockets/rails/quiet_assets.rb +18 -0
- data/lib/sprockets/rails/route_wrapper.rb +23 -0
- data/lib/sprockets/rails/task.rb +10 -15
- data/lib/sprockets/rails/utils.rb +11 -0
- data/lib/sprockets/rails/version.rb +1 -1
- data/lib/sprockets/railtie.rb +173 -75
- metadata +38 -43
- data/lib/sprockets/rails/legacy_asset_tag_helper.rb +0 -32
- data/lib/sprockets/rails/legacy_asset_url_helper.rb +0 -133
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 801a6cbc13340fb4c74ecf9b7aa2d5c6c563605e3462512e0073f268e269fe8d
|
4
|
+
data.tar.gz: facde95b73f355f987059128c7f6d852b5b8845d26f2eca5214b4fc37ded168d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f6c2f179ba5b3294ad0b49357c4a7a50c207f221d6cbb5d9cad406b1143ee5ff9d5a71897f3f6a2bd9709eda8d5e5bad5380e4defa1e135700cc3edd9669749
|
7
|
+
data.tar.gz: cbd34277b1e2e89c5ddded1b616ce179a269e384f1781b7032972c966737803e725440f5a23951383adf6b4a8705b50a307eb94a2bd6055ab42dcfc505aa468c
|
data/{LICENSE → MIT-LICENSE}
RENAMED
data/README.md
CHANGED
@@ -27,7 +27,7 @@ Only removes old assets (keeps the most recent 3 copies) from `public/assets`. U
|
|
27
27
|
|
28
28
|
**`rake assets:clobber`**
|
29
29
|
|
30
|
-
Nuke `public/assets
|
30
|
+
Nuke `public/assets`.
|
31
31
|
|
32
32
|
#### Customize
|
33
33
|
|
@@ -37,11 +37,6 @@ You can also redefine the task with the built in task generator.
|
|
37
37
|
|
38
38
|
``` ruby
|
39
39
|
require 'sprockets/rails/task'
|
40
|
-
# clean the old tasks
|
41
|
-
Rake::Task["assets:environment"].clear
|
42
|
-
Rake::Task["assets:precompile"].clear
|
43
|
-
Rake::Task["assets:clean"].clear
|
44
|
-
Rake::Task["assets:clobber"].clear
|
45
40
|
Sprockets::Rails::Task.new(Rails.application) do |t|
|
46
41
|
t.environment = lambda { Rails.application.assets }
|
47
42
|
t.assets = %w( application.js application.css )
|
@@ -51,23 +46,25 @@ end
|
|
51
46
|
|
52
47
|
Each asset task will invoke `assets:environment` first. By default this loads the Rails environment. You can override this task to add or remove dependencies for your specific compilation environment.
|
53
48
|
|
54
|
-
Also see [Sprockets::Rails::Task](https://github.com/rails/sprockets-rails/blob/master/lib/sprockets/rails/task.rb) and [Rake::SprocketsTask](https://github.com/
|
55
|
-
|
49
|
+
Also see [Sprockets::Rails::Task](https://github.com/rails/sprockets-rails/blob/master/lib/sprockets/rails/task.rb) and [Rake::SprocketsTask](https://github.com/rails/sprockets/blob/master/lib/rake/sprocketstask.rb).
|
56
50
|
|
57
51
|
### Initializer options
|
58
52
|
|
59
|
-
**`config.assets.
|
53
|
+
**`config.assets.unknown_asset_fallback`**
|
60
54
|
|
61
|
-
|
55
|
+
When set to a truthy value, a result will be returned even if the requested asset is not found in the asset pipeline. When set to a falsey value it will raise an error when no asset is found in the pipeline. Defaults to `true`.
|
62
56
|
|
63
|
-
**`config.assets.
|
57
|
+
**`config.assets.precompile`**
|
64
58
|
|
65
|
-
|
59
|
+
Add additional assets to compile on deploy. Defaults to `application.js`, `application.css` and any other non-js/css file under `app/assets`.
|
66
60
|
|
67
61
|
**`config.assets.paths`**
|
68
62
|
|
69
63
|
Add additional load paths to this Array. Rails includes `app/assets`, `lib/assets` and `vendor/assets` for you already. Plugins might want to add their custom paths to this.
|
70
64
|
|
65
|
+
**`config.assets.quiet`**
|
66
|
+
|
67
|
+
Suppresses logger output for asset requests. Uses the `config.assets.prefix` path to match asset requests. Defaults to `false`.
|
71
68
|
|
72
69
|
**`config.assets.version`**
|
73
70
|
|
@@ -83,13 +80,9 @@ config.assets.version = 'v2'
|
|
83
80
|
|
84
81
|
Defaults to `/assets`. Changes the directory to compile assets to.
|
85
82
|
|
86
|
-
**`config.assets.manifest`**
|
87
|
-
|
88
|
-
Defines the full path to be used for the asset precompiler's manifest file. Defaults to a randomly-generated filename in the `config.assets.prefix` directory within the public folder.
|
89
|
-
|
90
83
|
**`config.assets.digest`**
|
91
84
|
|
92
|
-
|
85
|
+
When enabled, fingerprints will be added to asset filenames.
|
93
86
|
|
94
87
|
**`config.assets.debug`**
|
95
88
|
|
@@ -97,7 +90,7 @@ Enable expanded asset debugging mode. Individual files will be served to make re
|
|
97
90
|
|
98
91
|
**`config.assets.compile`**
|
99
92
|
|
100
|
-
Enables Sprockets compile environment. If disabled, `Rails.application.assets` will be
|
93
|
+
Enables Sprockets compile environment. If disabled, `Rails.application.assets` will be `nil` to prevent inadvertent compilation calls. View helpers will depend on assets being precompiled to `public/assets` in order to link to them. Initializers expecting `Rails.application.assets` during boot should be accessing the environment in a `config.assets.configure` block. See below.
|
101
94
|
|
102
95
|
**`config.assets.configure`**
|
103
96
|
|
@@ -105,18 +98,38 @@ Invokes block with environment when the environment is initialized. Allows direc
|
|
105
98
|
|
106
99
|
``` ruby
|
107
100
|
config.assets.configure do |env|
|
108
|
-
env.js_compressor = :
|
101
|
+
env.js_compressor = :uglifier # or :closure, :yui
|
109
102
|
env.css_compressor = :sass # or :yui
|
110
103
|
|
111
104
|
require 'my_processor'
|
112
105
|
env.register_preprocessor 'application/javascript', MyProcessor
|
113
106
|
|
114
107
|
env.logger = Rails.logger
|
115
|
-
|
116
|
-
env.cache = ActiveSupport::Cache::FileStore.new("tmp/cache/assets")
|
117
108
|
end
|
118
109
|
```
|
119
110
|
|
111
|
+
**`config.assets.resolve_with`**
|
112
|
+
|
113
|
+
A list of `:environment` and `:manifest` symbols that defines the order that
|
114
|
+
we try to find assets: manifest first, environment second? Manifest only?
|
115
|
+
|
116
|
+
By default, we check the manifest first if asset digests are enabled and debug
|
117
|
+
is not enabled, then we check the environment if compiling is enabled:
|
118
|
+
```
|
119
|
+
# Dev where debug is true, or digests are disabled
|
120
|
+
%i[ environment ]
|
121
|
+
|
122
|
+
# Dev default, or production with compile enabled.
|
123
|
+
%i[ manifest environment ]
|
124
|
+
|
125
|
+
# Production default.
|
126
|
+
%i[ manifest ]
|
127
|
+
```
|
128
|
+
If the resolver list is empty (e.g. if debug is true and compile is false), the standard rails public path resolution will be used.
|
129
|
+
|
130
|
+
**`config.assets.check_precompiled_asset`**
|
131
|
+
|
132
|
+
When enabled, an exception is raised for missing assets. This option is enabled by default.
|
120
133
|
|
121
134
|
## Complementary plugins
|
122
135
|
|
@@ -125,36 +138,51 @@ The following plugins provide some extras for the Sprockets Asset Pipeline.
|
|
125
138
|
* [coffee-rails](https://github.com/rails/coffee-rails)
|
126
139
|
* [sass-rails](https://github.com/rails/sass-rails)
|
127
140
|
|
128
|
-
**NOTE** That these plugins are optional. The core coffee-script, sass, less, uglify, (
|
141
|
+
**NOTE** That these plugins are optional. The core coffee-script, sass, less, uglify, (and many more) features are built into Sprockets itself. Many of these plugins only provide generators and extra helpers. You can probably get by without them.
|
129
142
|
|
130
143
|
|
131
144
|
## Changes from Rails 3.x
|
132
145
|
|
133
146
|
* Only compiles digest filenames. Static non-digest assets should simply live in public/.
|
134
147
|
* Unmanaged asset paths and urls fallback to linking to public/. This should make it easier to work with both compiled assets and simple static assets. As a side effect, there will never be any "asset not precompiled errors" when linking to missing assets. They will just link to a public file which may or may not exist.
|
135
|
-
* JS and CSS compressors must be explicitly set. Magic detection has been removed to avoid loading compressors in environments where you want to avoid loading any of the asset libraries. Assign `config.assets.js_compressor = :
|
148
|
+
* JS and CSS compressors must be explicitly set. Magic detection has been removed to avoid loading compressors in environments where you want to avoid loading any of the asset libraries. Assign `config.assets.js_compressor = :uglifier` or `config.assets.css_compressor = :sass` for the standard compressors.
|
136
149
|
* The manifest file is now in a JSON format. Since it lives in public/ by default, the initial filename is also randomized to obfuscate public access to the resource.
|
137
150
|
* `config.assets.manifest` (if used) must now include the manifest filename, e.g. `Rails.root.join('config/manifest.json')`. It cannot be a directory.
|
138
|
-
* Two cleanup tasks
|
151
|
+
* Two cleanup tasks: `rake assets:clean` is now a safe cleanup that only removes older assets that are no longer used, while `rake assets:clobber` nukes the entire `public/assets` directory. The clean task allows for rolling deploys that may still be linking to an old asset while the new assets are being built.
|
152
|
+
|
153
|
+
### But what if I want sprockets to generate non-digest assets?
|
154
|
+
|
155
|
+
You have several options:
|
156
|
+
|
157
|
+
* Use the [non-digest-assets gem](https://github.com/mvz/non-digest-assets).
|
158
|
+
* Use the [sprockets-redirect gem](https://github.com/sikachu/sprockets-redirect).
|
159
|
+
* Use the [smart_assets gem](https://github.com/zarqman/smart_assets).
|
160
|
+
* Create [a rake task](https://github.com/rails/sprockets-rails/issues/49#issuecomment-20535134) to pre-generate a non-digest version in `public/`.
|
139
161
|
|
162
|
+
## Experimental
|
140
163
|
|
141
|
-
|
164
|
+
### [SRI](http://www.w3.org/TR/SRI/) support
|
142
165
|
|
143
|
-
|
166
|
+
Sprockets 3.x adds experimental support for subresource integrity checks. The spec is still evolving and the API may change in backwards incompatible ways.
|
144
167
|
|
145
|
-
```
|
146
|
-
|
147
|
-
|
148
|
-
$ bundle install
|
149
|
-
$ bundle exec rake test
|
168
|
+
``` ruby
|
169
|
+
javascript_include_tag :application, integrity: true
|
170
|
+
# => "<script src="/assets/application.js" integrity="sha256-TvVUHzSfftWg1rcfL6TIJ0XKEGrgLyEq6lEpcmrG9qs="></script>"
|
150
171
|
```
|
151
172
|
|
152
|
-
|
173
|
+
Note that sprockets-rails only adds integrity hashes to assets when served in a secure context (over an HTTPS connection or localhost).
|
174
|
+
|
175
|
+
|
176
|
+
## Contributing to Sprockets Rails
|
153
177
|
|
178
|
+
Sprockets Rails is work of many contributors. You're encouraged to submit pull requests, propose
|
179
|
+
features and discuss issues.
|
180
|
+
|
181
|
+
See [CONTRIBUTING](CONTRIBUTING.md).
|
154
182
|
|
155
183
|
## Releases
|
156
184
|
|
157
|
-
sprockets-rails
|
185
|
+
sprockets-rails 3.x will primarily target sprockets 3.x. And future versions will target the corresponding sprockets release line.
|
158
186
|
|
159
187
|
The minor and patch version will be updated according to [semver](http://semver.org/).
|
160
188
|
|
@@ -162,9 +190,11 @@ The minor and patch version will be updated according to [semver](http://semver.
|
|
162
190
|
* Any time the sprockets dependency is bumped, there will be a new minor release
|
163
191
|
* Simple bug fixes will be patch releases
|
164
192
|
|
165
|
-
|
166
193
|
## License
|
167
194
|
|
168
|
-
|
195
|
+
Sprockets Rails is released under the [MIT License](MIT-LICENSE).
|
196
|
+
|
197
|
+
## Code Status
|
169
198
|
|
170
|
-
|
199
|
+
* [](http://travis-ci.org/rails/sprockets-rails)
|
200
|
+
* [](http://badge.fury.io/rb/sprockets-rails)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'action_view/helpers'
|
2
|
+
require 'sprockets'
|
3
|
+
|
4
|
+
module Sprockets
|
5
|
+
module Rails
|
6
|
+
module Context
|
7
|
+
include ActionView::Helpers::AssetUrlHelper
|
8
|
+
include ActionView::Helpers::AssetTagHelper
|
9
|
+
|
10
|
+
def self.included(klass)
|
11
|
+
klass.class_eval do
|
12
|
+
class_attribute :config, :assets_prefix, :digest_assets
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def compute_asset_path(path, options = {})
|
17
|
+
@dependencies << 'actioncontroller-asset-url-config'
|
18
|
+
|
19
|
+
begin
|
20
|
+
asset_uri = resolve(path)
|
21
|
+
rescue FileNotFound
|
22
|
+
# TODO: eh, we should be able to use a form of locate that returns
|
23
|
+
# nil instead of raising an exception.
|
24
|
+
end
|
25
|
+
|
26
|
+
if asset_uri
|
27
|
+
asset = link_asset(path)
|
28
|
+
digest_path = asset.digest_path
|
29
|
+
path = digest_path if digest_assets
|
30
|
+
File.join(assets_prefix || "/", path)
|
31
|
+
else
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
register_dependency_resolver 'actioncontroller-asset-url-config' do |env|
|
39
|
+
config = env.context_class.config
|
40
|
+
[config.relative_url_root,
|
41
|
+
(config.asset_host unless config.asset_host.respond_to?(:call))]
|
42
|
+
end
|
43
|
+
|
44
|
+
# fallback to the default pipeline when using Sprockets 3.x
|
45
|
+
unless config[:pipelines].include? :debug
|
46
|
+
register_pipeline :debug, config[:pipelines][:default]
|
47
|
+
end
|
48
|
+
end
|
@@ -1,128 +1,132 @@
|
|
1
1
|
require 'action_view'
|
2
2
|
require 'sprockets'
|
3
3
|
require 'active_support/core_ext/class/attribute'
|
4
|
+
require 'sprockets/rails/utils'
|
4
5
|
|
5
6
|
module Sprockets
|
6
7
|
module Rails
|
7
8
|
module Helper
|
8
|
-
class
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
def precompile
|
13
|
-
Sprockets::Rails::Helper.precompile
|
14
|
-
end
|
15
|
-
|
16
|
-
def assets
|
17
|
-
Sprockets::Rails::Helper.assets
|
18
|
-
end
|
19
|
-
|
20
|
-
def raise_runtime_errors
|
21
|
-
Sprockets::Rails::Helper.raise_runtime_errors
|
22
|
-
end
|
9
|
+
class AssetNotFound < StandardError; end
|
10
|
+
class AssetNotPrecompiled < StandardError; end
|
23
11
|
|
24
|
-
class
|
12
|
+
class AssetNotPrecompiledError < AssetNotPrecompiled
|
13
|
+
include Sprockets::Rails::Utils
|
25
14
|
def initialize(source)
|
26
|
-
msg =
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
15
|
+
msg =
|
16
|
+
if using_sprockets4?
|
17
|
+
"Asset `#{ source }` was not declared to be precompiled in production.\n" +
|
18
|
+
"Declare links to your assets in `app/assets/config/manifest.js`.\n\n" +
|
19
|
+
" //= link #{ source }\n\n" +
|
20
|
+
"and restart your server"
|
21
|
+
else
|
22
|
+
"Asset was not declared to be precompiled in production.\n" +
|
23
|
+
"Add `Rails.application.config.assets.precompile += " +
|
24
|
+
"%w( #{source} )` to `config/initializers/assets.rb` and " +
|
25
|
+
"restart your server"
|
26
|
+
end
|
37
27
|
super(msg)
|
38
28
|
end
|
39
29
|
end
|
40
30
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
else
|
45
|
-
require 'sprockets/rails/legacy_asset_tag_helper'
|
46
|
-
require 'sprockets/rails/legacy_asset_url_helper'
|
47
|
-
include LegacyAssetTagHelper
|
48
|
-
include LegacyAssetUrlHelper
|
49
|
-
end
|
31
|
+
include ActionView::Helpers::AssetUrlHelper
|
32
|
+
include ActionView::Helpers::AssetTagHelper
|
33
|
+
include Sprockets::Rails::Utils
|
50
34
|
|
51
|
-
VIEW_ACCESSORS = [
|
52
|
-
|
35
|
+
VIEW_ACCESSORS = [
|
36
|
+
:assets_environment, :assets_manifest,
|
37
|
+
:assets_precompile, :precompiled_asset_checker,
|
38
|
+
:assets_prefix, :digest_assets, :debug_assets,
|
39
|
+
:resolve_assets_with, :check_precompiled_asset,
|
40
|
+
:unknown_asset_fallback
|
41
|
+
]
|
53
42
|
|
54
43
|
def self.included(klass)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
44
|
+
klass.class_attribute(*VIEW_ACCESSORS)
|
45
|
+
|
46
|
+
klass.class_eval do
|
47
|
+
remove_method :assets_environment
|
48
|
+
def assets_environment
|
49
|
+
if instance_variable_defined?(:@assets_environment)
|
50
|
+
@assets_environment = @assets_environment.cached
|
51
|
+
elsif env = self.class.assets_environment
|
52
|
+
@assets_environment = env.cached
|
53
|
+
else
|
54
|
+
nil
|
55
|
+
end
|
60
56
|
end
|
61
|
-
else
|
62
|
-
klass.class_attribute(*VIEW_ACCESSORS)
|
63
57
|
end
|
64
58
|
end
|
65
59
|
|
66
60
|
def self.extended(obj)
|
67
|
-
obj.class_eval do
|
61
|
+
obj.singleton_class.class_eval do
|
68
62
|
attr_accessor(*VIEW_ACCESSORS)
|
63
|
+
|
64
|
+
remove_method :assets_environment
|
65
|
+
def assets_environment
|
66
|
+
if env = @assets_environment
|
67
|
+
@assets_environment = env.cached
|
68
|
+
else
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
end
|
69
72
|
end
|
70
73
|
end
|
71
74
|
|
75
|
+
# Writes over the built in ActionView::Helpers::AssetUrlHelper#compute_asset_path
|
76
|
+
# to use the asset pipeline.
|
72
77
|
def compute_asset_path(path, options = {})
|
73
|
-
|
74
|
-
check_dependencies!(path) if defined?(depend_on)
|
78
|
+
debug = options[:debug]
|
75
79
|
|
76
|
-
if
|
77
|
-
|
78
|
-
path += "?body=1" if options[:debug]
|
79
|
-
File.join(assets_prefix || "/", path)
|
80
|
+
if asset_path = resolve_asset_path(path, debug)
|
81
|
+
File.join(assets_prefix || "/", legacy_debug_path(asset_path, debug))
|
80
82
|
else
|
83
|
+
message = "The asset #{ path.inspect } is not present in the asset pipeline.\n"
|
84
|
+
raise AssetNotFound, message unless unknown_asset_fallback
|
85
|
+
|
86
|
+
if respond_to?(:public_compute_asset_path)
|
87
|
+
message << "Falling back to an asset that may be in the public folder.\n"
|
88
|
+
message << "This behavior is deprecated and will be removed.\n"
|
89
|
+
message << "To bypass the asset pipeline and preserve this behavior,\n"
|
90
|
+
message << "use the `skip_pipeline: true` option.\n"
|
91
|
+
|
92
|
+
call_stack = Kernel.respond_to?(:caller_locations) && ::Rails::VERSION::MAJOR >= 5 ? caller_locations : caller
|
93
|
+
ActiveSupport::Deprecation.warn(message, call_stack)
|
94
|
+
end
|
81
95
|
super
|
82
96
|
end
|
83
97
|
end
|
84
98
|
|
85
|
-
#
|
86
|
-
#
|
87
|
-
def
|
88
|
-
|
89
|
-
|
99
|
+
# Resolve the asset path against the Sprockets manifest or environment.
|
100
|
+
# Returns nil if it's an asset we don't know about.
|
101
|
+
def resolve_asset_path(path, allow_non_precompiled = false) #:nodoc:
|
102
|
+
resolve_asset do |resolver|
|
103
|
+
resolver.asset_path path, digest_assets, allow_non_precompiled
|
90
104
|
end
|
91
|
-
super(source, options)
|
92
105
|
end
|
93
|
-
alias :path_to_asset :asset_path
|
94
106
|
|
95
|
-
#
|
107
|
+
# Expand asset path to digested form.
|
96
108
|
#
|
97
109
|
# path - String path
|
98
110
|
# options - Hash options
|
99
111
|
#
|
100
|
-
# Returns String
|
101
|
-
def
|
102
|
-
|
103
|
-
|
104
|
-
if digest_path = asset_digest_path(path, options)
|
105
|
-
digest_path[/-(.+)\./, 1]
|
112
|
+
# Returns String path or nil if no asset was found.
|
113
|
+
def asset_digest_path(path, options = {})
|
114
|
+
resolve_asset do |resolver|
|
115
|
+
resolver.digest_path path, options[:debug]
|
106
116
|
end
|
107
117
|
end
|
108
118
|
|
109
|
-
#
|
119
|
+
# Experimental: Get integrity for asset path.
|
110
120
|
#
|
111
121
|
# path - String path
|
112
122
|
# options - Hash options
|
113
123
|
#
|
114
|
-
# Returns String
|
115
|
-
def
|
116
|
-
|
117
|
-
if digest_path = manifest.assets[path]
|
118
|
-
return digest_path
|
119
|
-
end
|
120
|
-
end
|
124
|
+
# Returns String integrity attribute or nil if no asset was found.
|
125
|
+
def asset_integrity(path, options = {})
|
126
|
+
path = path_with_extname(path, options)
|
121
127
|
|
122
|
-
|
123
|
-
|
124
|
-
return asset.digest_path
|
125
|
-
end
|
128
|
+
resolve_asset do |resolver|
|
129
|
+
resolver.integrity path
|
126
130
|
end
|
127
131
|
end
|
128
132
|
|
@@ -131,21 +135,27 @@ module Sprockets
|
|
131
135
|
# Eventually will be deprecated and replaced by source maps.
|
132
136
|
def javascript_include_tag(*sources)
|
133
137
|
options = sources.extract_options!.stringify_keys
|
138
|
+
integrity = compute_integrity?(options)
|
134
139
|
|
135
140
|
if options["debug"] != false && request_debug_assets?
|
136
141
|
sources.map { |source|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
142
|
+
if asset = lookup_debug_asset(source, type: :javascript)
|
143
|
+
if asset.respond_to?(:to_a)
|
144
|
+
asset.to_a.map do |a|
|
145
|
+
super(path_to_javascript(a.logical_path, debug: true), options)
|
146
|
+
end
|
147
|
+
else
|
148
|
+
super(path_to_javascript(asset.logical_path, debug: true), options)
|
141
149
|
end
|
142
150
|
else
|
143
151
|
super(source, options)
|
144
152
|
end
|
145
153
|
}.flatten.uniq.join("\n").html_safe
|
146
154
|
else
|
147
|
-
sources.
|
148
|
-
|
155
|
+
sources.map { |source|
|
156
|
+
options = options.merge('integrity' => asset_integrity(source, type: :javascript)) if integrity
|
157
|
+
super source, options
|
158
|
+
}.join("\n").html_safe
|
149
159
|
end
|
150
160
|
end
|
151
161
|
|
@@ -154,81 +164,214 @@ module Sprockets
|
|
154
164
|
# Eventually will be deprecated and replaced by source maps.
|
155
165
|
def stylesheet_link_tag(*sources)
|
156
166
|
options = sources.extract_options!.stringify_keys
|
167
|
+
integrity = compute_integrity?(options)
|
168
|
+
|
157
169
|
if options["debug"] != false && request_debug_assets?
|
158
170
|
sources.map { |source|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
171
|
+
if asset = lookup_debug_asset(source, type: :stylesheet)
|
172
|
+
if asset.respond_to?(:to_a)
|
173
|
+
asset.to_a.map do |a|
|
174
|
+
super(path_to_stylesheet(a.logical_path, debug: true), options)
|
175
|
+
end
|
176
|
+
else
|
177
|
+
super(path_to_stylesheet(asset.logical_path, debug: true), options)
|
163
178
|
end
|
164
179
|
else
|
165
180
|
super(source, options)
|
166
181
|
end
|
167
182
|
}.flatten.uniq.join("\n").html_safe
|
168
183
|
else
|
169
|
-
sources.
|
170
|
-
|
184
|
+
sources.map { |source|
|
185
|
+
options = options.merge('integrity' => asset_integrity(source, type: :stylesheet)) if integrity
|
186
|
+
super source, options
|
187
|
+
}.join("\n").html_safe
|
171
188
|
end
|
172
189
|
end
|
173
190
|
|
174
191
|
protected
|
175
|
-
#
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
192
|
+
# This is awkward: `integrity` is a boolean option indicating whether
|
193
|
+
# we want to include or omit the subresource integrity hash, but the
|
194
|
+
# options hash is also passed through as literal tag attributes.
|
195
|
+
# That means we have to delete the shortcut boolean option so it
|
196
|
+
# doesn't bleed into the tag attributes, but also check its value if
|
197
|
+
# it's boolean-ish.
|
198
|
+
def compute_integrity?(options)
|
199
|
+
if secure_subresource_integrity_context?
|
200
|
+
case options['integrity']
|
201
|
+
when nil, false, true
|
202
|
+
options.delete('integrity') == true
|
203
|
+
end
|
204
|
+
else
|
205
|
+
options.delete 'integrity'
|
206
|
+
false
|
207
|
+
end
|
180
208
|
end
|
181
209
|
|
182
|
-
#
|
183
|
-
#
|
184
|
-
def
|
185
|
-
|
210
|
+
# Only serve integrity metadata for HTTPS requests:
|
211
|
+
# http://www.w3.org/TR/SRI/#non-secure-contexts-remain-non-secure
|
212
|
+
def secure_subresource_integrity_context?
|
213
|
+
respond_to?(:request) && self.request && (self.request.local? || self.request.ssl?)
|
214
|
+
end
|
186
215
|
|
187
|
-
|
188
|
-
|
216
|
+
# Enable split asset debugging. Eventually will be deprecated
|
217
|
+
# and replaced by source maps in Sprockets 3.x.
|
218
|
+
def request_debug_assets?
|
219
|
+
debug_assets || (defined?(controller) && controller && params[:debug_assets])
|
220
|
+
rescue # FIXME: what exactly are we rescuing?
|
221
|
+
false
|
222
|
+
end
|
189
223
|
|
190
|
-
|
224
|
+
# Internal method to support multifile debugging. Will
|
225
|
+
# eventually be removed w/ Sprockets 3.x.
|
226
|
+
def lookup_debug_asset(path, options = {})
|
227
|
+
path = path_with_extname(path, options)
|
191
228
|
|
192
|
-
|
193
|
-
|
229
|
+
resolve_asset do |resolver|
|
230
|
+
resolver.find_debug_asset path
|
194
231
|
end
|
232
|
+
end
|
195
233
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
234
|
+
# compute_asset_extname is in AV::Helpers::AssetUrlHelper
|
235
|
+
def path_with_extname(path, options)
|
236
|
+
path = path.to_s
|
237
|
+
"#{path}#{compute_asset_extname(path, options)}"
|
238
|
+
end
|
239
|
+
|
240
|
+
# Try each asset resolver and return the first non-nil result.
|
241
|
+
def resolve_asset
|
242
|
+
asset_resolver_strategies.detect do |resolver|
|
243
|
+
if result = yield(resolver)
|
244
|
+
break result
|
201
245
|
end
|
202
246
|
end
|
203
247
|
end
|
204
248
|
|
205
|
-
#
|
206
|
-
def
|
207
|
-
|
208
|
-
|
249
|
+
# List of resolvers in `config.assets.resolve_with` order.
|
250
|
+
def asset_resolver_strategies
|
251
|
+
@asset_resolver_strategies ||=
|
252
|
+
Array(resolve_assets_with).map do |name|
|
253
|
+
HelperAssetResolvers[name].new(self)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
# Append ?body=1 if debug is on and we're on old Sprockets.
|
258
|
+
def legacy_debug_path(path, debug)
|
259
|
+
if debug && !using_sprockets4?
|
260
|
+
"#{path}?body=1"
|
209
261
|
else
|
210
|
-
|
262
|
+
path
|
211
263
|
end
|
212
264
|
end
|
265
|
+
end
|
213
266
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
267
|
+
# Use a separate module since Helper is mixed in and we needn't pollute
|
268
|
+
# the class namespace with our internals.
|
269
|
+
module HelperAssetResolvers #:nodoc:
|
270
|
+
def self.[](name)
|
271
|
+
case name
|
272
|
+
when :manifest
|
273
|
+
Manifest
|
274
|
+
when :environment
|
275
|
+
Environment
|
276
|
+
else
|
277
|
+
raise ArgumentError, "Unrecognized asset resolver: #{name.inspect}. Expected :manifest or :environment"
|
220
278
|
end
|
279
|
+
end
|
221
280
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
281
|
+
class Manifest #:nodoc:
|
282
|
+
def initialize(view)
|
283
|
+
@manifest = view.assets_manifest
|
284
|
+
raise ArgumentError, 'config.assets.resolve_with includes :manifest, but app.assets_manifest is nil' unless @manifest
|
285
|
+
end
|
286
|
+
|
287
|
+
def asset_path(path, digest, allow_non_precompiled = false)
|
288
|
+
if digest
|
289
|
+
digest_path path, allow_non_precompiled
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def digest_path(path, allow_non_precompiled = false)
|
294
|
+
@manifest.assets[path]
|
295
|
+
end
|
296
|
+
|
297
|
+
def integrity(path)
|
298
|
+
if meta = metadata(path)
|
299
|
+
meta["integrity"]
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def find_debug_asset(path)
|
304
|
+
nil
|
305
|
+
end
|
306
|
+
|
307
|
+
private
|
308
|
+
def metadata(path)
|
309
|
+
if digest_path = digest_path(path)
|
310
|
+
@manifest.files[digest_path]
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
class Environment #:nodoc:
|
316
|
+
def initialize(view)
|
317
|
+
raise ArgumentError, 'config.assets.resolve_with includes :environment, but app.assets is nil' unless view.assets_environment
|
318
|
+
@env = view.assets_environment
|
319
|
+
@precompiled_asset_checker = view.precompiled_asset_checker
|
320
|
+
@check_precompiled_asset = view.check_precompiled_asset
|
321
|
+
end
|
322
|
+
|
323
|
+
def asset_path(path, digest, allow_non_precompiled = false)
|
324
|
+
# Digests enabled? Do the work to calculate the full asset path.
|
325
|
+
if digest
|
326
|
+
digest_path path, allow_non_precompiled
|
327
|
+
|
328
|
+
# Otherwise, ask the Sprockets environment whether the asset exists
|
329
|
+
# and check whether it's also precompiled for production deploys.
|
330
|
+
elsif asset = find_asset(path)
|
331
|
+
raise_unless_precompiled_asset asset.logical_path unless allow_non_precompiled
|
332
|
+
path
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
def digest_path(path, allow_non_precompiled = false)
|
337
|
+
if asset = find_asset(path)
|
338
|
+
raise_unless_precompiled_asset asset.logical_path unless allow_non_precompiled
|
339
|
+
asset.digest_path
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
def integrity(path)
|
344
|
+
find_asset(path).try :integrity
|
345
|
+
end
|
346
|
+
|
347
|
+
def find_debug_asset(path)
|
348
|
+
if asset = find_asset(path, pipeline: :debug)
|
349
|
+
raise_unless_precompiled_asset asset.logical_path.sub('.debug', '')
|
350
|
+
asset
|
229
351
|
end
|
230
|
-
env[path]
|
231
352
|
end
|
353
|
+
|
354
|
+
private
|
355
|
+
if RUBY_VERSION >= "2.7"
|
356
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
357
|
+
def find_asset(path, options = {})
|
358
|
+
@env[path, **options]
|
359
|
+
end
|
360
|
+
RUBY
|
361
|
+
else
|
362
|
+
def find_asset(path, options = {})
|
363
|
+
@env[path, options]
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
def precompiled?(path)
|
368
|
+
@precompiled_asset_checker.call path
|
369
|
+
end
|
370
|
+
|
371
|
+
def raise_unless_precompiled_asset(path)
|
372
|
+
raise Helper::AssetNotPrecompiled.new(path) if @check_precompiled_asset && !precompiled?(path)
|
373
|
+
end
|
374
|
+
end
|
232
375
|
end
|
233
376
|
end
|
234
377
|
end
|