├── .devcontainer
└── devcontainer.json
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── CONTRIBUTING.md
├── Gemfile
├── MIT-LICENSE
├── README.md
├── Rakefile
├── gemfiles
├── Gemfile.rails-6.1-sprockets-3
├── Gemfile.rails-6.1-sprockets-4
├── Gemfile.rails-7.0-sprockets-3
├── Gemfile.rails-7.0-sprockets-4
├── Gemfile.rails-7.1-sprockets-3
├── Gemfile.rails-7.1-sprockets-4
├── Gemfile.rails-7.2-sprockets-3
├── Gemfile.rails-7.2-sprockets-4
├── Gemfile.rails-8.0-sprockets-3
└── Gemfile.rails-8.0-sprockets-4
├── lib
└── sprockets
│ ├── rails.rb
│ ├── rails
│ ├── asset_url_processor.rb
│ ├── context.rb
│ ├── deprecator.rb
│ ├── helper.rb
│ ├── quiet_assets.rb
│ ├── route_wrapper.rb
│ ├── sourcemapping_url_processor.rb
│ ├── task.rb
│ ├── utils.rb
│ └── version.rb
│ └── railtie.rb
├── sprockets-rails.gemspec
└── test
├── fixtures
├── bar.css
├── bar.js
├── bundle
│ └── index.js
├── dependency.css
├── dependency.js
├── error
│ ├── dependency.js.erb
│ └── missing.css.erb
├── file1.css
├── file1.js
├── file2.css
├── file2.js
├── foo.css
├── foo.js
├── jquery
│ ├── bower.json
│ └── jquery.js
├── logo.png
├── manifest.js
├── not_precompiled.css
├── not_precompiled.js
├── url.css.erb
└── url.js.erb
├── test_asset_url_processor.rb
├── test_helper.rb
├── test_quiet_assets.rb
├── test_railtie.rb
├── test_sourcemapping_url_processor.rb
└── test_task.rb
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2 | // README at: https://github.com/devcontainers/templates/tree/main/src/ruby
3 | {
4 | "name": "sprockets-rails",
5 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
6 | "image": "ghcr.io/rails/devcontainer/images/ruby:3.2.5",
7 |
8 | // Features to add to the dev container. More info: https://containers.dev/features.
9 | "features": {
10 | "ghcr.io/devcontainers/features/github-cli:1": {
11 | "version": "latest"
12 | }
13 | }
14 |
15 | // Use 'forwardPorts' to make a list of ports inside the container available locally.
16 | // "forwardPorts": [],
17 |
18 | // Use 'postCreateCommand' to run commands after the container is created.
19 | // "postCreateCommand": "ruby --version",
20 |
21 | // Configure tool-specific properties.
22 | // "customizations": {},
23 |
24 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
25 | // "remoteUser": "root"
26 | }
27 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on: [push, pull_request]
3 | jobs:
4 | tests:
5 | runs-on: ubuntu-latest
6 | strategy:
7 | fail-fast: false
8 | matrix:
9 | include:
10 | - ruby: 2.5
11 | gemfile: "gemfiles/Gemfile.rails-6.1-sprockets-3"
12 | - ruby: 2.5
13 | gemfile: "gemfiles/Gemfile.rails-6.1-sprockets-4"
14 |
15 | - ruby: 2.7
16 | gemfile: "gemfiles/Gemfile.rails-7.0-sprockets-3"
17 | - ruby: 2.7
18 | gemfile: "gemfiles/Gemfile.rails-7.0-sprockets-4"
19 |
20 | - ruby: 2.7
21 | gemfile: "gemfiles/Gemfile.rails-7.1-sprockets-3"
22 | - ruby: 2.7
23 | gemfile: "gemfiles/Gemfile.rails-7.1-sprockets-4"
24 |
25 | - ruby: 3.1
26 | gemfile: "gemfiles/Gemfile.rails-7.2-sprockets-3"
27 | - ruby: 3.1
28 | gemfile: "gemfiles/Gemfile.rails-7.2-sprockets-4"
29 |
30 | - ruby: 3.2
31 | gemfile: "gemfiles/Gemfile.rails-8.0-sprockets-3"
32 | - ruby: 3.2
33 | gemfile: "gemfiles/Gemfile.rails-8.0-sprockets-4"
34 |
35 | - ruby: 3.2
36 | gemfile: Gemfile
37 | - ruby: 3.3
38 | gemfile: Gemfile
39 | - ruby: head
40 | gemfile: Gemfile
41 |
42 | env:
43 | BUNDLE_GEMFILE: ${{ matrix.gemfile }}
44 |
45 | steps:
46 | - uses: actions/checkout@v3
47 | - name: Set up Ruby
48 | uses: ruby/setup-ruby@v1
49 | with:
50 | ruby-version: ${{ matrix.ruby }}
51 | bundler-cache: true
52 | - name: Run tests
53 | run: bundle exec rake
54 | continue-on-error: ${{ matrix.gemfile == 'Gemfile' }}
55 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Gemfile*.lock
2 | tmp/
3 | *.gem
4 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributing to Sprockets Rails
2 | =====================
3 |
4 | Sprockets Rails is work of [many contributors](https://github.com/rails/sprockets-rails/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/rails/sprockets-rails/pulls), [propose features and discuss issues](https://github.com/rails/sprockets-rails/issues).
5 |
6 | #### Fork the Project
7 |
8 | Fork the [project on GitHub](https://github.com/rails/sprockets-rails) and clone your fork.
9 | Use your GitHub username instead of `YOUR-USERNAME`.
10 |
11 | ```
12 | git clone https://github.com/YOUR-USERNAME/sprockets-rails.git
13 | cd sprockets-rails
14 | git remote add upstream https://github.com/rails/sprockets-rails.git
15 | ```
16 |
17 | #### Create a Topic Branch
18 |
19 | Make sure your fork is up-to-date and create a topic branch for your feature or bug fix.
20 |
21 | ```
22 | git checkout master
23 | git pull upstream master
24 | git checkout -b my-feature-branch
25 | ```
26 |
27 | #### Bundle Install and Test
28 |
29 | Ensure that you can build the project and run tests.
30 |
31 | ```
32 | bundle install
33 | bundle exec rake test
34 | ```
35 |
36 | #### Write Tests
37 |
38 | Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build. Add to [test](test).
39 |
40 | We definitely appreciate pull requests that highlight or reproduce a problem, even without a fix.
41 |
42 | #### Write Code
43 |
44 | Implement your feature or bug fix.
45 |
46 | Make sure that `bundle exec rake test` completes without errors.
47 |
48 | #### Write Documentation
49 |
50 | Document any external behavior in the [README](README.md).
51 |
52 | #### Commit Changes
53 |
54 | Make sure git knows your name and email address:
55 |
56 | ```
57 | git config --global user.name "Your Name"
58 | git config --global user.email "contributor@example.com"
59 | ```
60 |
61 | Writing good commit logs is important. A commit log should describe what changed and why.
62 |
63 | ```
64 | git add ...
65 | git commit
66 | ```
67 |
68 | #### Push
69 |
70 | ```
71 | git push origin my-feature-branch
72 | ```
73 |
74 | #### Make a Pull Request
75 |
76 | Go to https://github.com/contributor/sprockets-rails and select your feature branch. Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
77 |
78 | #### Rebase
79 |
80 | If you've been working on a change for a while, rebase with upstream/master.
81 |
82 | ```
83 | git fetch upstream
84 | git rebase upstream/master
85 | git push origin my-feature-branch -f
86 | ```
87 |
88 | #### Check on Your Pull Request
89 |
90 | Go back to your pull request after a few minutes and see whether it passed muster with Travis-CI. Everything should look green, otherwise fix issues and amend your commit as described above.
91 |
92 | #### Be Patient
93 |
94 | It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang on there!
95 |
96 | #### Thank You
97 |
98 | Please do know that we really appreciate and value your time and work. We love you, really.
99 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec
3 |
4 | gem 'actionpack', github: 'rails/rails', branch: 'main'
5 | gem 'railties', github: 'rails/rails', branch: 'main'
6 | gem 'rack', '~> 2.2'
7 | gem 'sprockets', github: 'rails/sprockets', branch: '3.x'
8 |
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014-2016 Joshua Peek
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Sprockets Rails
2 |
3 | Provides [Sprockets](https://github.com/rails/sprockets) implementation for Rails 4.x (and beyond) Asset Pipeline.
4 |
5 |
6 | ## Installation
7 |
8 | ``` ruby
9 | gem 'sprockets-rails', :require => 'sprockets/railtie'
10 | ```
11 |
12 | Or alternatively `require 'sprockets/railtie'` in your `config/application.rb` if you have Bundler auto-require disabled.
13 |
14 |
15 | ## Usage
16 |
17 |
18 | ### Rake task
19 |
20 | **`rake assets:precompile`**
21 |
22 | Deployment task that compiles any assets listed in `config.assets.precompile` to `public/assets`.
23 |
24 | **`rake assets:clean`**
25 |
26 | Only removes old assets (keeps the most recent 3 copies) from `public/assets`. Useful when doing rolling deploys that may still be serving old assets while the new ones are being compiled.
27 |
28 | **`rake assets:clobber`**
29 |
30 | Nuke `public/assets`.
31 |
32 | #### Customize
33 |
34 | If the basic tasks don't do all that you need, it's straight forward to redefine them and replace them with something more specific to your app.
35 |
36 | You can also redefine the task with the built in task generator.
37 |
38 | ``` ruby
39 | require 'sprockets/rails/task'
40 | Sprockets::Rails::Task.new(Rails.application) do |t|
41 | t.environment = lambda { Rails.application.assets }
42 | t.assets = %w( application.js application.css )
43 | t.keep = 5
44 | end
45 | ```
46 |
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.
48 |
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).
50 |
51 | ### Initializer options
52 |
53 | **`config.assets.unknown_asset_fallback`**
54 |
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`.
56 |
57 | **`config.assets.precompile`**
58 |
59 | Add additional assets to compile on deploy. Defaults to `application.js`, `application.css` and any other non-js/css file under `app/assets`.
60 |
61 | **`config.assets.paths`**
62 |
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.
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`.
68 |
69 | **`config.assets.version`**
70 |
71 | Set a custom cache buster string. Changing it will cause all assets to recompile on the next build.
72 |
73 | ``` ruby
74 | config.assets.version = 'v1'
75 | # after installing a new plugin, change loads paths
76 | config.assets.version = 'v2'
77 | ```
78 |
79 | **`config.assets.prefix`**
80 |
81 | Defaults to `/assets`. Changes the directory to compile assets to.
82 |
83 | **`config.assets.digest`**
84 |
85 | When enabled, fingerprints will be added to asset filenames.
86 |
87 | **`config.assets.debug`**
88 |
89 | Enable asset debugging mode. A source map will be included with each asset when this is true.
90 |
91 | **`config.assets.compile`**
92 |
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.
94 |
95 | **`config.assets.configure`**
96 |
97 | Invokes block with environment when the environment is initialized. Allows direct access to the environment instance and lets you lazily load libraries only needed for asset compiling.
98 |
99 | ``` ruby
100 | config.assets.configure do |env|
101 | env.js_compressor = :uglifier # or :closure, :yui
102 | env.css_compressor = :sass # or :yui
103 |
104 | require 'my_processor'
105 | env.register_preprocessor 'application/javascript', MyProcessor
106 |
107 | env.logger = Rails.logger
108 | end
109 | ```
110 |
111 | **`config.assets.resolve_assets_in_css_urls`**
112 |
113 | When this option is enabled, sprockets-rails will register a CSS postprocessor to resolve assets referenced in [`url()`](https://developer.mozilla.org/en-US/docs/Web/CSS/url()) function calls and replace them with the digested paths. Defaults to `true`.
114 |
115 | **`config.assets.resolve_with`**
116 |
117 | A list of `:environment` and `:manifest` symbols that defines the order that
118 | we try to find assets: manifest first, environment second? Manifest only?
119 |
120 | By default, we check the manifest first if asset digests are enabled and debug
121 | is not enabled, then we check the environment if compiling is enabled:
122 | ```
123 | # Dev where debug is true, or digests are disabled
124 | %i[ environment ]
125 |
126 | # Dev default, or production with compile enabled.
127 | %i[ manifest environment ]
128 |
129 | # Production default.
130 | %i[ manifest ]
131 | ```
132 | 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.
133 |
134 | **`config.assets.check_precompiled_asset`**
135 |
136 | When enabled, an exception is raised for missing assets. This option is enabled by default.
137 |
138 | ## Complementary plugins
139 |
140 | The following plugins provide some extras for the Sprockets Asset Pipeline.
141 |
142 | * [coffee-rails](https://github.com/rails/coffee-rails)
143 | * [sass-rails](https://github.com/rails/sass-rails)
144 |
145 | **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.
146 |
147 |
148 | ## Changes from Rails 3.x
149 |
150 | * Only compiles digest filenames. Static non-digest assets should simply live in public/.
151 | * 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.
152 | * 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.
153 | * 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.
154 | * `config.assets.manifest` (if used) must now include the manifest filename, e.g. `Rails.root.join('config/manifest.json')`. It cannot be a directory.
155 | * 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.
156 |
157 | ### But what if I want sprockets to generate non-digest assets?
158 |
159 | You have several options:
160 |
161 | * Use the [non-digest-assets gem](https://github.com/mvz/non-digest-assets).
162 | * Use the [sprockets-redirect gem](https://github.com/sikachu/sprockets-redirect).
163 | * Use the [smart_assets gem](https://github.com/zarqman/smart_assets).
164 | * Create [a rake task](https://github.com/rails/sprockets-rails/issues/49#issuecomment-20535134) to pre-generate a non-digest version in `public/`.
165 |
166 | ## Experimental
167 |
168 | ### [SRI](http://www.w3.org/TR/SRI/) support
169 |
170 | Sprockets 3.x adds experimental support for subresource integrity checks. The spec is still evolving and the API may change in backwards incompatible ways.
171 |
172 | ``` ruby
173 | javascript_include_tag :application, integrity: true
174 | # => ""
175 | ```
176 |
177 | Note that sprockets-rails only adds integrity hashes to assets when served in a secure context (over an HTTPS connection or localhost).
178 |
179 |
180 | ## Contributing to Sprockets Rails
181 |
182 | Sprockets Rails is work of many contributors. You're encouraged to submit pull requests, propose
183 | features and discuss issues.
184 |
185 | See [CONTRIBUTING](CONTRIBUTING.md).
186 |
187 | ## Releases
188 |
189 | sprockets-rails 3.x will primarily target sprockets 3.x. And future versions will target the corresponding sprockets release line.
190 |
191 | The minor and patch version will be updated according to [semver](http://semver.org/).
192 |
193 | * Any new APIs or config options that don't break compatibility will be in a minor release
194 | * Any time the sprockets dependency is bumped, there will be a new minor release
195 | * Simple bug fixes will be patch releases
196 |
197 | ## License
198 |
199 | Sprockets Rails is released under the [MIT License](MIT-LICENSE).
200 |
201 | ## Code Status
202 |
203 | * [](http://badge.fury.io/rb/sprockets-rails)
204 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'rake/testtask'
2 | require 'bundler/gem_tasks'
3 |
4 | task :default => :test
5 |
6 | Rake::TestTask.new(:test) do |t|
7 | t.libs << 'lib'
8 | t.pattern = 'test/test_*.rb'
9 | t.warning = true
10 | t.verbose = true
11 | end
12 |
--------------------------------------------------------------------------------
/gemfiles/Gemfile.rails-6.1-sprockets-3:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec path: '..'
3 |
4 | gem 'actionpack', '~> 6.1.0'
5 | gem 'railties', '~> 6.1.0'
6 | gem 'sprockets', '~> 3.0'
7 |
--------------------------------------------------------------------------------
/gemfiles/Gemfile.rails-6.1-sprockets-4:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec path: '..'
3 |
4 | gem 'actionpack', '~> 6.1.0'
5 | gem 'railties', '~> 6.1.0'
6 | gem 'sprockets', '~> 4.0'
7 |
--------------------------------------------------------------------------------
/gemfiles/Gemfile.rails-7.0-sprockets-3:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec path: '..'
3 |
4 | gem 'actionpack', '~> 7.0.0'
5 | gem 'railties', '~> 7.0.0'
6 | gem 'sprockets', '~> 3.0'
7 |
--------------------------------------------------------------------------------
/gemfiles/Gemfile.rails-7.0-sprockets-4:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec path: '..'
3 |
4 | gem 'actionpack', '~> 7.0.0'
5 | gem 'railties', '~> 7.0.0'
6 | gem 'sprockets', '~> 4.0'
7 |
--------------------------------------------------------------------------------
/gemfiles/Gemfile.rails-7.1-sprockets-3:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec path: '..'
3 |
4 | gem 'actionpack', '~> 7.1.0'
5 | gem 'railties', '~> 7.1.0'
6 | gem 'sprockets', '~> 3.0'
7 |
--------------------------------------------------------------------------------
/gemfiles/Gemfile.rails-7.1-sprockets-4:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec path: '..'
3 |
4 | gem 'actionpack', '~> 7.1.0'
5 | gem 'railties', '~> 7.1.0'
6 | gem 'sprockets', '~> 4.0'
7 |
--------------------------------------------------------------------------------
/gemfiles/Gemfile.rails-7.2-sprockets-3:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec path: '..'
3 |
4 | gem 'actionpack', '~> 7.2.0'
5 | gem 'railties', '~> 7.2.0'
6 | gem 'sprockets', '~> 3.0'
7 |
--------------------------------------------------------------------------------
/gemfiles/Gemfile.rails-7.2-sprockets-4:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec path: '..'
3 |
4 | gem 'actionpack', '~> 7.2.0'
5 | gem 'railties', '~> 7.2.0'
6 | gem 'sprockets', '~> 4.0'
7 |
--------------------------------------------------------------------------------
/gemfiles/Gemfile.rails-8.0-sprockets-3:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec path: '..'
3 |
4 | gem 'actionpack', '~> 8.0.0.rc1'
5 | gem 'railties', '~> 8.0.0.rc1'
6 | gem 'sprockets', '~> 3.0'
7 |
--------------------------------------------------------------------------------
/gemfiles/Gemfile.rails-8.0-sprockets-4:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | gemspec path: '..'
3 |
4 | gem 'actionpack', '~> 8.0.0.rc1'
5 | gem 'railties', '~> 8.0.0.rc1'
6 | gem 'sprockets', '~> 4.0'
7 |
--------------------------------------------------------------------------------
/lib/sprockets/rails.rb:
--------------------------------------------------------------------------------
1 | require 'sprockets/rails/version'
2 | if defined? Rails::Railtie
3 | require 'sprockets/railtie'
4 | end
5 | require 'sprockets/rails/deprecator'
6 |
--------------------------------------------------------------------------------
/lib/sprockets/rails/asset_url_processor.rb:
--------------------------------------------------------------------------------
1 | module Sprockets
2 | module Rails
3 | # Resolve assets referenced in CSS `url()` calls and replace them with the digested paths
4 | class AssetUrlProcessor
5 | REGEX = /url\(\s*["']?(?!(?:\#|data|http))(?\.\/)?(?[^"'\s)]+)\s*["']?\)/
6 | def self.call(input)
7 | context = input[:environment].context_class.new(input)
8 | data = input[:data].gsub(REGEX) do |_match|
9 | path = Regexp.last_match[:path]
10 | "url(#{context.asset_path(path)})"
11 | end
12 |
13 | context.metadata.merge(data: data)
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/lib/sprockets/rails/context.rb:
--------------------------------------------------------------------------------
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
49 |
--------------------------------------------------------------------------------
/lib/sprockets/rails/deprecator.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "active_support"
4 |
5 | module Sprockets
6 | module Rails
7 | def self.deprecator
8 | @deprecator ||= ActiveSupport::Deprecation.new("4.0", "Sprockets::Rails")
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/lib/sprockets/rails/helper.rb:
--------------------------------------------------------------------------------
1 | require 'action_view'
2 | require 'sprockets'
3 | require 'active_support/core_ext/class/attribute'
4 | require 'sprockets/rails/utils'
5 |
6 | module Sprockets
7 | module Rails
8 | module Helper
9 | class AssetNotFound < StandardError; end
10 | class AssetNotPrecompiled < StandardError; end
11 |
12 | class AssetNotPrecompiledError < AssetNotPrecompiled
13 | include Sprockets::Rails::Utils
14 | def initialize(source)
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
27 | super(msg)
28 | end
29 | end
30 |
31 | include ActionView::Helpers::AssetUrlHelper
32 | include ActionView::Helpers::AssetTagHelper
33 | include Sprockets::Rails::Utils
34 |
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 | ]
42 |
43 | def self.included(klass)
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
56 | end
57 | end
58 | end
59 |
60 | def self.extended(obj)
61 | obj.singleton_class.class_eval do
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
72 | end
73 | end
74 |
75 | # Writes over the built in ActionView::Helpers::AssetUrlHelper#compute_asset_path
76 | # to use the asset pipeline.
77 | def compute_asset_path(path, options = {})
78 | debug = options[:debug]
79 |
80 | if asset_path = resolve_asset_path(path, debug)
81 | File.join(assets_prefix || "/", legacy_debug_path(asset_path, debug))
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 | Sprockets::Rails.deprecator.warn(message, caller_locations)
93 | end
94 | super
95 | end
96 | end
97 |
98 | # Resolve the asset path against the Sprockets manifest or environment.
99 | # Returns nil if it's an asset we don't know about.
100 | def resolve_asset_path(path, allow_non_precompiled = false) #:nodoc:
101 | resolve_asset do |resolver|
102 | resolver.asset_path path, digest_assets, allow_non_precompiled
103 | end
104 | end
105 |
106 | # Expand asset path to digested form.
107 | #
108 | # path - String path
109 | # options - Hash options
110 | #
111 | # Returns String path or nil if no asset was found.
112 | def asset_digest_path(path, options = {})
113 | resolve_asset do |resolver|
114 | resolver.digest_path path, options[:debug]
115 | end
116 | end
117 |
118 | # Experimental: Get integrity for asset path.
119 | #
120 | # path - String path
121 | # options - Hash options
122 | #
123 | # Returns String integrity attribute or nil if no asset was found.
124 | def asset_integrity(path, options = {})
125 | path = path_with_extname(path, options)
126 |
127 | resolve_asset do |resolver|
128 | resolver.integrity path
129 | end
130 | end
131 |
132 | # Override javascript tag helper to provide debugging support.
133 | #
134 | # Eventually will be deprecated and replaced by source maps.
135 | def javascript_include_tag(*sources)
136 | options = sources.extract_options!.stringify_keys
137 | integrity = compute_integrity?(options)
138 |
139 | if options["debug"] != false && request_debug_assets?
140 | sources.map { |source|
141 | if asset = lookup_debug_asset(source, type: :javascript)
142 | if asset.respond_to?(:to_a)
143 | asset.to_a.map do |a|
144 | super(path_to_javascript(a.logical_path, debug: true), options)
145 | end
146 | else
147 | super(path_to_javascript(asset.logical_path, debug: true), options)
148 | end
149 | else
150 | super(source, options)
151 | end
152 | }.flatten.uniq.join("\n").html_safe
153 | else
154 | sources.map { |source|
155 | options = options.merge('integrity' => asset_integrity(source, type: :javascript)) if integrity
156 | super source, options
157 | }.join("\n").html_safe
158 | end
159 | end
160 |
161 | # Override stylesheet tag helper to provide debugging support.
162 | #
163 | # Eventually will be deprecated and replaced by source maps.
164 | def stylesheet_link_tag(*sources)
165 | options = sources.extract_options!.stringify_keys
166 | integrity = compute_integrity?(options)
167 |
168 | if options["debug"] != false && request_debug_assets?
169 | sources.map { |source|
170 | if asset = lookup_debug_asset(source, type: :stylesheet)
171 | if asset.respond_to?(:to_a)
172 | asset.to_a.map do |a|
173 | super(path_to_stylesheet(a.logical_path, debug: true), options)
174 | end
175 | else
176 | super(path_to_stylesheet(asset.logical_path, debug: true), options)
177 | end
178 | else
179 | super(source, options)
180 | end
181 | }.flatten.uniq.join("\n").html_safe
182 | else
183 | sources.map { |source|
184 | options = options.merge('integrity' => asset_integrity(source, type: :stylesheet)) if integrity
185 | super source, options
186 | }.join("\n").html_safe
187 | end
188 | end
189 |
190 | protected
191 | # This is awkward: `integrity` is a boolean option indicating whether
192 | # we want to include or omit the subresource integrity hash, but the
193 | # options hash is also passed through as literal tag attributes.
194 | # That means we have to delete the shortcut boolean option so it
195 | # doesn't bleed into the tag attributes, but also check its value if
196 | # it's boolean-ish.
197 | def compute_integrity?(options)
198 | if secure_subresource_integrity_context?
199 | case options['integrity']
200 | when nil, false, true
201 | options.delete('integrity') == true
202 | end
203 | else
204 | options.delete 'integrity'
205 | false
206 | end
207 | end
208 |
209 | # Only serve integrity metadata for HTTPS requests:
210 | # http://www.w3.org/TR/SRI/#non-secure-contexts-remain-non-secure
211 | def secure_subresource_integrity_context?
212 | respond_to?(:request) && self.request && (self.request.local? || self.request.ssl?)
213 | end
214 |
215 | # Enable split asset debugging. Eventually will be deprecated
216 | # and replaced by source maps in Sprockets 3.x.
217 | def request_debug_assets?
218 | debug_assets || (defined?(controller) && controller && params[:debug_assets])
219 | rescue # FIXME: what exactly are we rescuing?
220 | false
221 | end
222 |
223 | # Internal method to support multifile debugging. Will
224 | # eventually be removed w/ Sprockets 3.x.
225 | def lookup_debug_asset(path, options = {})
226 | path = path_with_extname(path, options)
227 |
228 | resolve_asset do |resolver|
229 | resolver.find_debug_asset path
230 | end
231 | end
232 |
233 | # compute_asset_extname is in AV::Helpers::AssetUrlHelper
234 | def path_with_extname(path, options)
235 | path = path.to_s
236 | "#{path}#{compute_asset_extname(path, options)}"
237 | end
238 |
239 | # Try each asset resolver and return the first non-nil result.
240 | def resolve_asset
241 | asset_resolver_strategies.detect do |resolver|
242 | if result = yield(resolver)
243 | break result
244 | end
245 | end
246 | end
247 |
248 | # List of resolvers in `config.assets.resolve_with` order.
249 | def asset_resolver_strategies
250 | @asset_resolver_strategies ||=
251 | Array(resolve_assets_with).map do |name|
252 | HelperAssetResolvers[name].new(self)
253 | end
254 | end
255 |
256 | # Append ?body=1 if debug is on and we're on old Sprockets.
257 | def legacy_debug_path(path, debug)
258 | if debug && !using_sprockets4?
259 | "#{path}?body=1"
260 | else
261 | path
262 | end
263 | end
264 | end
265 |
266 | # Use a separate module since Helper is mixed in and we needn't pollute
267 | # the class namespace with our internals.
268 | module HelperAssetResolvers #:nodoc:
269 | def self.[](name)
270 | case name
271 | when :manifest
272 | Manifest
273 | when :environment
274 | Environment
275 | else
276 | raise ArgumentError, "Unrecognized asset resolver: #{name.inspect}. Expected :manifest or :environment"
277 | end
278 | end
279 |
280 | class Manifest #:nodoc:
281 | def initialize(view)
282 | @manifest = view.assets_manifest
283 | raise ArgumentError, 'config.assets.resolve_with includes :manifest, but app.assets_manifest is nil' unless @manifest
284 | end
285 |
286 | def asset_path(path, digest, allow_non_precompiled = false)
287 | if digest
288 | digest_path path, allow_non_precompiled
289 | end
290 | end
291 |
292 | def digest_path(path, allow_non_precompiled = false)
293 | @manifest.assets[path]
294 | end
295 |
296 | def integrity(path)
297 | if meta = metadata(path)
298 | meta["integrity"]
299 | end
300 | end
301 |
302 | def find_debug_asset(path)
303 | nil
304 | end
305 |
306 | private
307 | def metadata(path)
308 | if digest_path = digest_path(path)
309 | @manifest.files[digest_path]
310 | end
311 | end
312 | end
313 |
314 | class Environment #:nodoc:
315 | def initialize(view)
316 | raise ArgumentError, 'config.assets.resolve_with includes :environment, but app.assets is nil' unless view.assets_environment
317 | @env = view.assets_environment
318 | @precompiled_asset_checker = view.precompiled_asset_checker
319 | @check_precompiled_asset = view.check_precompiled_asset
320 | end
321 |
322 | def asset_path(path, digest, allow_non_precompiled = false)
323 | # Digests enabled? Do the work to calculate the full asset path.
324 | if digest
325 | digest_path path, allow_non_precompiled
326 |
327 | # Otherwise, ask the Sprockets environment whether the asset exists
328 | # and check whether it's also precompiled for production deploys.
329 | elsif asset = find_asset(path)
330 | raise_unless_precompiled_asset asset.logical_path unless allow_non_precompiled
331 | path
332 | end
333 | end
334 |
335 | def digest_path(path, allow_non_precompiled = false)
336 | if asset = find_asset(path)
337 | raise_unless_precompiled_asset asset.logical_path unless allow_non_precompiled
338 | asset.digest_path
339 | end
340 | end
341 |
342 | def integrity(path)
343 | find_asset(path).try :integrity
344 | end
345 |
346 | def find_debug_asset(path)
347 | if asset = find_asset(path, pipeline: :debug)
348 | raise_unless_precompiled_asset asset.logical_path.sub('.debug', '')
349 | asset
350 | end
351 | end
352 |
353 | private
354 | if RUBY_VERSION >= "2.7"
355 | class_eval <<-RUBY, __FILE__, __LINE__ + 1
356 | def find_asset(path, options = {})
357 | @env[path, **options]
358 | end
359 | RUBY
360 | else
361 | def find_asset(path, options = {})
362 | @env[path, options]
363 | end
364 | end
365 |
366 | def precompiled?(path)
367 | @precompiled_asset_checker.call path
368 | end
369 |
370 | def raise_unless_precompiled_asset(path)
371 | raise Helper::AssetNotPrecompiledError.new(path) if @check_precompiled_asset && !precompiled?(path)
372 | end
373 | end
374 | end
375 | end
376 | end
377 |
--------------------------------------------------------------------------------
/lib/sprockets/rails/quiet_assets.rb:
--------------------------------------------------------------------------------
1 | module Sprockets
2 | module Rails
3 | class LoggerSilenceError < StandardError; end
4 |
5 | class QuietAssets
6 | def initialize(app)
7 | @app = app
8 | @assets_regex = %r(\A/{0,2}#{::Rails.application.config.assets.prefix})
9 | end
10 |
11 | def call(env)
12 | if env['PATH_INFO'] =~ @assets_regex
13 | raise_logger_silence_error unless ::Rails.logger.respond_to?(:silence)
14 |
15 | ::Rails.logger.silence { @app.call(env) }
16 | else
17 | @app.call(env)
18 | end
19 | end
20 |
21 | private
22 | def raise_logger_silence_error
23 | error = <<~ERROR
24 | You have enabled `config.assets.quiet`, but your `Rails.logger`
25 | does not use the `LoggerSilence` module.
26 |
27 | Please use a compatible logger such as `ActiveSupport::Logger`
28 | to take advantage of quiet asset logging.
29 |
30 | ERROR
31 |
32 | raise LoggerSilenceError, error
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/lib/sprockets/rails/route_wrapper.rb:
--------------------------------------------------------------------------------
1 | module Sprockets
2 | module Rails
3 | module RouteWrapper
4 | def internal_assets_path?
5 | path =~ %r{\A#{self.class.assets_prefix}\z}
6 | end
7 |
8 | def internal?
9 | super || internal_assets_path?
10 | end
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/lib/sprockets/rails/sourcemapping_url_processor.rb:
--------------------------------------------------------------------------------
1 | module Sprockets
2 | module Rails
3 | # Rewrites source mapping urls with the digested paths and protect against semicolon appending with a dummy comment line
4 | class SourcemappingUrlProcessor
5 | REGEX = /\/\/# sourceMappingURL=(.*\.map)/
6 |
7 | class << self
8 | def call(input)
9 | env = input[:environment]
10 | context = env.context_class.new(input)
11 | data = input[:data].gsub(REGEX) do |_match|
12 | sourcemap_logical_path = combine_sourcemap_logical_path(sourcefile: input[:name], sourcemap: $1)
13 |
14 | begin
15 | resolved_sourcemap_comment(sourcemap_logical_path, context: context)
16 | rescue Sprockets::FileNotFound
17 | removed_sourcemap_comment(sourcemap_logical_path, filename: input[:filename], env: env)
18 | end
19 | end
20 |
21 | { data: data }
22 | end
23 |
24 | private
25 | def combine_sourcemap_logical_path(sourcefile:, sourcemap:)
26 | if (parts = sourcefile.split("/")).many?
27 | parts[0..-2].append(sourcemap).join("/")
28 | else
29 | sourcemap
30 | end
31 | end
32 |
33 | def resolved_sourcemap_comment(sourcemap_logical_path, context:)
34 | "//# sourceMappingURL=#{sourcemap_asset_path(sourcemap_logical_path, context: context)}\n//!\n"
35 | end
36 |
37 | def sourcemap_asset_path(sourcemap_logical_path, context:)
38 | # FIXME: Work-around for bug where if the sourcemap is nested two levels deep, it'll resolve as the source file
39 | # that's being mapped, rather than the map itself. So context.resolve("a/b/c.js.map") will return "c.js?"
40 | if context.resolve(sourcemap_logical_path) =~ /\.map/
41 | context.asset_path(sourcemap_logical_path)
42 | else
43 | raise Sprockets::FileNotFound, "Failed to resolve source map asset due to nesting depth"
44 | end
45 | end
46 |
47 | def removed_sourcemap_comment(sourcemap_logical_path, filename:, env:)
48 | env.logger.warn "Removed sourceMappingURL comment for missing asset '#{sourcemap_logical_path}' from #{filename}"
49 | nil
50 | end
51 | end
52 | end
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/lib/sprockets/rails/task.rb:
--------------------------------------------------------------------------------
1 | require 'rake'
2 | require 'rake/sprocketstask'
3 | require 'sprockets'
4 | require 'action_view'
5 |
6 | module Sprockets
7 | module Rails
8 | class Task < Rake::SprocketsTask
9 | attr_accessor :app
10 |
11 | def initialize(app = nil)
12 | self.app = app
13 | super()
14 | end
15 |
16 | def environment
17 | if app
18 | # Use initialized app.assets or force build an environment if
19 | # config.assets.compile is disabled
20 | app.assets || Sprockets::Railtie.build_environment(app)
21 | else
22 | super
23 | end
24 | end
25 |
26 | def output
27 | if app
28 | config = app.config
29 | File.join(config.paths['public'].first, config.assets.prefix)
30 | else
31 | super
32 | end
33 | end
34 |
35 | def assets
36 | if app
37 | app.config.assets.precompile
38 | else
39 | super
40 | end
41 | end
42 |
43 | def manifest
44 | if app
45 | Sprockets::Manifest.new(index, output, app.config.assets.manifest)
46 | else
47 | super
48 | end
49 | end
50 |
51 | def define
52 | namespace :assets do
53 | %w( environment precompile clean clobber ).each do |task|
54 | Rake::Task[task].clear if Rake::Task.task_defined?(task)
55 | end
56 |
57 | # Override this task change the loaded dependencies
58 | desc "Load asset compile environment"
59 | task :environment do
60 | # Load full Rails environment by default
61 | Rake::Task['environment'].invoke
62 | end
63 |
64 | desc "Compile all the assets named in config.assets.precompile"
65 | task :precompile => :environment do
66 | with_logger do
67 | manifest.compile(assets)
68 | end
69 | end
70 |
71 | desc "Remove old compiled assets"
72 | task :clean, [:keep] => :environment do |t, args|
73 | with_logger do
74 | manifest.clean(Integer(args.keep || self.keep))
75 | end
76 | end
77 |
78 | desc "Remove compiled assets"
79 | task :clobber => :environment do
80 | with_logger do
81 | manifest.clobber
82 | end
83 | end
84 | end
85 | end
86 | end
87 | end
88 | end
89 |
--------------------------------------------------------------------------------
/lib/sprockets/rails/utils.rb:
--------------------------------------------------------------------------------
1 | require 'sprockets'
2 |
3 | module Sprockets
4 | module Rails
5 | module Utils
6 | def using_sprockets4?
7 | Gem::Version.new(Sprockets::VERSION) >= Gem::Version.new('4.x')
8 | end
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/lib/sprockets/rails/version.rb:
--------------------------------------------------------------------------------
1 | module Sprockets
2 | module Rails
3 | VERSION = "3.5.2"
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/lib/sprockets/railtie.rb:
--------------------------------------------------------------------------------
1 | require 'rails'
2 | require 'rails/railtie'
3 | require 'action_controller/railtie'
4 | require 'active_support/core_ext/module/remove_method'
5 | require 'active_support/core_ext/numeric/bytes'
6 | require 'sprockets'
7 |
8 | require 'sprockets/rails/asset_url_processor'
9 | require 'sprockets/rails/deprecator'
10 | require 'sprockets/rails/sourcemapping_url_processor'
11 | require 'sprockets/rails/context'
12 | require 'sprockets/rails/helper'
13 | require 'sprockets/rails/quiet_assets'
14 | require 'sprockets/rails/route_wrapper'
15 | require 'sprockets/rails/version'
16 | require 'set'
17 |
18 | module Rails
19 | class Application
20 | # Hack: We need to remove Rails' built in config.assets so we can
21 | # do our own thing.
22 | class Configuration
23 | remove_possible_method :assets
24 | end
25 |
26 | # Undefine Rails' assets method before redefining it, to avoid warnings.
27 | remove_possible_method :assets
28 | remove_possible_method :assets=
29 |
30 | # Returns Sprockets::Environment for app config.
31 | attr_accessor :assets
32 |
33 | # Returns Sprockets::Manifest for app config.
34 | attr_accessor :assets_manifest
35 |
36 | # Called from asset helpers to alert you if you reference an asset URL that
37 | # isn't precompiled and hence won't be available in production.
38 | def asset_precompiled?(logical_path)
39 | if precompiled_assets.include?(logical_path)
40 | true
41 | elsif !config.cache_classes
42 | # Check to see if precompile list has been updated
43 | precompiled_assets(true).include?(logical_path)
44 | else
45 | false
46 | end
47 | end
48 |
49 | # Lazy-load the precompile list so we don't cause asset compilation at app
50 | # boot time, but ensure we cache the list so we don't recompute it for each
51 | # request or test case.
52 | def precompiled_assets(clear_cache = false)
53 | @precompiled_assets = nil if clear_cache
54 | @precompiled_assets ||= assets_manifest.find(config.assets.precompile).map(&:logical_path).to_set
55 | end
56 | end
57 | end
58 |
59 | module Sprockets
60 | class Railtie < ::Rails::Railtie
61 | include Sprockets::Rails::Utils
62 |
63 | class ManifestNeededError < StandardError
64 | def initialize
65 | msg = "Expected to find a manifest file in `app/assets/config/manifest.js`\n" +
66 | "But did not, please create this file and use it to link any assets that need\n" +
67 | "to be rendered by your app:\n\n" +
68 | "Example:\n" +
69 | " //= link_tree ../images\n" +
70 | " //= link_directory ../javascripts .js\n" +
71 | " //= link_directory ../stylesheets .css\n" +
72 | "and restart your server\n\n" +
73 | "For more information see: https://github.com/rails/sprockets/blob/070fc01947c111d35bb4c836e9bb71962a8e0595/UPGRADING.md#manifestjs"
74 | super msg
75 | end
76 | end
77 |
78 | LOOSE_APP_ASSETS = lambda do |logical_path, filename|
79 | filename.start_with?(::Rails.root.join("app/assets").to_s) &&
80 | !['.js', '.css', ''].include?(File.extname(logical_path))
81 | end
82 |
83 | class OrderedOptions < ActiveSupport::OrderedOptions
84 | def configure(&block)
85 | self._blocks << block
86 | end
87 | end
88 |
89 | ::Rails::Engine.initializer :append_assets_path, :group => :all do |app|
90 | app.config.assets.paths.unshift(*paths["vendor/assets"].existent_directories)
91 | app.config.assets.paths.unshift(*paths["lib/assets"].existent_directories)
92 | app.config.assets.paths.unshift(*paths["app/assets"].existent_directories)
93 | end
94 |
95 | config.assets = OrderedOptions.new
96 | config.assets._blocks = []
97 | config.assets.paths = []
98 | config.assets.precompile = []
99 | config.assets.prefix = "/assets"
100 | config.assets.manifest = nil
101 | config.assets.quiet = false
102 | config.assets.resolve_assets_in_css_urls = true
103 |
104 | initializer :set_default_precompile do |app|
105 | if using_sprockets4?
106 | raise ManifestNeededError unless ::Rails.root.join("app/assets/config/manifest.js").exist?
107 | app.config.assets.precompile += %w( manifest.js )
108 | else
109 | app.config.assets.precompile += [LOOSE_APP_ASSETS, /(?:\/|\\|\A)application\.(css|js)$/]
110 | end
111 | end
112 |
113 | initializer :quiet_assets do |app|
114 | if app.config.assets.quiet
115 | app.middleware.insert_before ::Rails::Rack::Logger, ::Sprockets::Rails::QuietAssets
116 | end
117 | end
118 |
119 | initializer :asset_url_processor do |app|
120 | if app.config.assets.resolve_assets_in_css_urls
121 | Sprockets.register_postprocessor "text/css", ::Sprockets::Rails::AssetUrlProcessor
122 | end
123 | end
124 |
125 | initializer :asset_sourcemap_url_processor do |app|
126 | Sprockets.register_postprocessor "application/javascript", ::Sprockets::Rails::SourcemappingUrlProcessor
127 | end
128 |
129 | initializer "sprockets-rails.deprecator" do |app|
130 | app.deprecators[:sprockets_rails] = Sprockets::Rails.deprecator if app.respond_to?(:deprecators)
131 | end
132 |
133 | config.assets.version = ""
134 | config.assets.debug = false
135 | config.assets.compile = true
136 | config.assets.digest = true
137 | config.assets.cache_limit = 50.megabytes
138 | config.assets.gzip = true
139 | config.assets.check_precompiled_asset = true
140 | config.assets.unknown_asset_fallback = true
141 |
142 | config.assets.configure do |env|
143 | config.assets.paths.each { |path| env.append_path(path) }
144 | end
145 |
146 | config.assets.configure do |env|
147 | env.context_class.send :include, ::Sprockets::Rails::Context
148 | env.context_class.assets_prefix = config.assets.prefix
149 | env.context_class.digest_assets = config.assets.digest
150 | env.context_class.config = config.action_controller
151 | end
152 |
153 | config.assets.configure do |env|
154 | env.cache = Sprockets::Cache::FileStore.new(
155 | "#{env.root}/tmp/cache/assets",
156 | config.assets.cache_limit,
157 | env.logger
158 | )
159 | end
160 |
161 | Sprockets.register_dependency_resolver 'rails-env' do
162 | ::Rails.env.to_s
163 | end
164 |
165 | config.assets.configure do |env|
166 | env.depend_on 'rails-env'
167 | end
168 |
169 | config.assets.configure do |env|
170 | env.version = config.assets.version
171 | end
172 |
173 | config.assets.configure do |env|
174 | env.gzip = config.assets.gzip if env.respond_to?(:gzip=)
175 | end
176 |
177 | rake_tasks do |app|
178 | require 'sprockets/rails/task'
179 | Sprockets::Rails::Task.new(app)
180 | end
181 |
182 | def build_environment(app, initialized = nil)
183 | initialized = app.initialized? if initialized.nil?
184 | unless initialized
185 | ::Rails.logger.warn "Application uninitialized: Try calling YourApp::Application.initialize!"
186 | end
187 |
188 | env = Sprockets::Environment.new(app.root.to_s)
189 |
190 | config = app.config
191 |
192 | # Run app.assets.configure blocks
193 | config.assets._blocks.each do |block|
194 | block.call(env)
195 | end
196 |
197 | # Set compressors after the configure blocks since they can
198 | # define new compressors and we only accept existent compressors.
199 | env.js_compressor = config.assets.js_compressor
200 | env.css_compressor = config.assets.css_compressor
201 |
202 | # No more configuration changes at this point.
203 | # With cache classes on, Sprockets won't check the FS when files
204 | # change. Preferable in production when the FS only changes on
205 | # deploys when the app restarts.
206 | if config.cache_classes
207 | env = env.cached
208 | end
209 |
210 | env
211 | end
212 |
213 | def self.build_manifest(app)
214 | config = app.config
215 | path = File.join(config.paths['public'].first, config.assets.prefix)
216 | Sprockets::Manifest.new(app.assets, path, config.assets.manifest)
217 | end
218 |
219 | config.after_initialize do |app|
220 | config = app.config
221 |
222 | if config.assets.compile
223 | app.assets = self.build_environment(app, true)
224 | app.routes.prepend do
225 | mount app.assets, at: config.assets.prefix
226 | end
227 | end
228 |
229 | app.assets_manifest = build_manifest(app)
230 |
231 | if config.assets.resolve_with.nil?
232 | config.assets.resolve_with = []
233 | config.assets.resolve_with << :manifest if config.assets.digest && !config.assets.debug
234 | config.assets.resolve_with << :environment if config.assets.compile
235 | end
236 |
237 | ActionDispatch::Routing::RouteWrapper.class_eval do
238 | class_attribute :assets_prefix
239 |
240 | prepend Sprockets::Rails::RouteWrapper
241 |
242 | self.assets_prefix = config.assets.prefix
243 | end
244 |
245 | ActiveSupport.on_load(:action_view) do
246 | include Sprockets::Rails::Helper
247 |
248 | # Copy relevant config to AV context
249 | self.debug_assets = config.assets.debug
250 | self.digest_assets = config.assets.digest
251 | self.assets_prefix = config.assets.prefix
252 | self.assets_precompile = config.assets.precompile
253 |
254 | self.assets_environment = app.assets
255 | self.assets_manifest = app.assets_manifest
256 |
257 | self.resolve_assets_with = config.assets.resolve_with
258 |
259 | self.check_precompiled_asset = config.assets.check_precompiled_asset
260 | self.unknown_asset_fallback = config.assets.unknown_asset_fallback
261 | # Expose the app precompiled asset check to the view
262 | self.precompiled_asset_checker = -> logical_path { app.asset_precompiled? logical_path }
263 | end
264 | end
265 | end
266 | end
267 |
--------------------------------------------------------------------------------
/sprockets-rails.gemspec:
--------------------------------------------------------------------------------
1 | $:.unshift File.expand_path("../lib", __FILE__)
2 | require "sprockets/rails/version"
3 |
4 | Gem::Specification.new do |s|
5 | s.name = "sprockets-rails"
6 | s.version = Sprockets::Rails::VERSION
7 |
8 | s.homepage = "https://github.com/rails/sprockets-rails"
9 | s.summary = "Sprockets Rails integration"
10 | s.license = "MIT"
11 |
12 | s.metadata = {
13 | "changelog_uri" => "#{s.homepage}/releases/tag/v#{s.version}"
14 | }
15 |
16 | s.files = Dir["README.md", "lib/**/*.rb", "MIT-LICENSE"]
17 |
18 | s.required_ruby_version = '>= 2.5'
19 |
20 | s.add_dependency "sprockets", ">= 3.0.0"
21 | s.add_dependency "actionpack", ">= 6.1"
22 | s.add_dependency "activesupport", ">= 6.1"
23 | s.add_development_dependency "railties", ">= 6.1"
24 | s.add_development_dependency "rake"
25 | s.add_development_dependency "sass"
26 | s.add_development_dependency "uglifier"
27 |
28 | s.author = "Joshua Peek"
29 | s.email = "josh@joshpeek.com"
30 | end
31 |
--------------------------------------------------------------------------------
/test/fixtures/bar.css:
--------------------------------------------------------------------------------
1 | /*= require foo */
2 |
--------------------------------------------------------------------------------
/test/fixtures/bar.js:
--------------------------------------------------------------------------------
1 | //= require foo
2 | var Bar;
3 |
--------------------------------------------------------------------------------
/test/fixtures/bundle/index.js:
--------------------------------------------------------------------------------
1 | var jQuery;
2 |
--------------------------------------------------------------------------------
/test/fixtures/dependency.css:
--------------------------------------------------------------------------------
1 | /* dependency */
2 |
--------------------------------------------------------------------------------
/test/fixtures/dependency.js:
--------------------------------------------------------------------------------
1 | // dependency
2 |
--------------------------------------------------------------------------------
/test/fixtures/error/dependency.js.erb:
--------------------------------------------------------------------------------
1 | <%= asset_path("bar.js") %>
2 |
--------------------------------------------------------------------------------
/test/fixtures/error/missing.css.erb:
--------------------------------------------------------------------------------
1 | p { background: url(<%= image_path "does_not_exist.png" %>); }
2 |
--------------------------------------------------------------------------------
/test/fixtures/file1.css:
--------------------------------------------------------------------------------
1 | /*= require dependency
2 | */
3 |
--------------------------------------------------------------------------------
/test/fixtures/file1.js:
--------------------------------------------------------------------------------
1 | //= require dependency
2 |
--------------------------------------------------------------------------------
/test/fixtures/file2.css:
--------------------------------------------------------------------------------
1 | /*= require dependency
2 | */
3 |
--------------------------------------------------------------------------------
/test/fixtures/file2.js:
--------------------------------------------------------------------------------
1 | //= require dependency
2 |
--------------------------------------------------------------------------------
/test/fixtures/foo.css:
--------------------------------------------------------------------------------
1 | .foo {}
2 |
--------------------------------------------------------------------------------
/test/fixtures/foo.js:
--------------------------------------------------------------------------------
1 | var Foo;
--------------------------------------------------------------------------------
/test/fixtures/jquery/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery",
3 | "main": "./jquery.js"
4 | }
5 |
--------------------------------------------------------------------------------
/test/fixtures/jquery/jquery.js:
--------------------------------------------------------------------------------
1 | var jQuery;
2 |
--------------------------------------------------------------------------------
/test/fixtures/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rails/sprockets-rails/266ec49f3c7c96018dd75f9dc4f9b62fe3f7eecf/test/fixtures/logo.png
--------------------------------------------------------------------------------
/test/fixtures/manifest.js:
--------------------------------------------------------------------------------
1 | // manifest.js
2 | //= link foo.css
3 | //= link foo.js
4 | //= link bar.css
5 | //= link bar.js
6 | //= link file1.css
7 | //= link file1.js
8 | //= link file2.css
9 | //= link file2.js
10 | //= link bundle.js
11 |
--------------------------------------------------------------------------------
/test/fixtures/not_precompiled.css:
--------------------------------------------------------------------------------
1 | .not-precompiled {}
2 |
--------------------------------------------------------------------------------
/test/fixtures/not_precompiled.js:
--------------------------------------------------------------------------------
1 | var not_precompiled;
2 |
--------------------------------------------------------------------------------
/test/fixtures/url.css.erb:
--------------------------------------------------------------------------------
1 | p { background: url(<%= image_path "logo.png" %>); }
2 |
--------------------------------------------------------------------------------
/test/fixtures/url.js.erb:
--------------------------------------------------------------------------------
1 | var url = '<%= javascript_path :foo %>';
2 |
--------------------------------------------------------------------------------
/test/test_asset_url_processor.rb:
--------------------------------------------------------------------------------
1 | require 'minitest/autorun'
2 | require 'sprockets/railtie'
3 |
4 |
5 | Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
6 | class TestAssetUrlProcessor < Minitest::Test
7 | FIXTURES_PATH = File.expand_path("../fixtures", __FILE__)
8 |
9 | def setup
10 | @env = Sprockets::Environment.new
11 | @env.append_path FIXTURES_PATH
12 | @env.context_class.class_eval do
13 | include ::Sprockets::Rails::Context
14 | end
15 | @env.context_class.digest_assets = true
16 |
17 | @logo_digest = @env["logo.png"].etag
18 | @logo_uri = @env["logo.png"].uri
19 | end
20 |
21 | def test_basic
22 | input = { environment: @env, data: 'background: url(logo.png);', filename: 'url2.css', metadata: {} }
23 | output = Sprockets::Rails::AssetUrlProcessor.call(input)
24 | assert_equal("background: url(/logo-#{@logo_digest}.png);", output[:data])
25 | end
26 |
27 | def test_spaces
28 | input = { environment: @env, data: 'background: url( logo.png );', filename: 'url2.css', metadata: {} }
29 | output = Sprockets::Rails::AssetUrlProcessor.call(input)
30 | assert_equal("background: url(/logo-#{@logo_digest}.png);", output[:data])
31 | end
32 |
33 | def test_single_quote
34 | input = { environment: @env, data: "background: url('logo.png');", filename: 'url2.css', metadata: {} }
35 | output = Sprockets::Rails::AssetUrlProcessor.call(input)
36 | assert_equal("background: url(/logo-#{@logo_digest}.png);", output[:data])
37 | end
38 |
39 | def test_double_quote
40 | input = { environment: @env, data: 'background: url("logo.png");', filename: 'url2.css', metadata: {} }
41 | output = Sprockets::Rails::AssetUrlProcessor.call(input)
42 | assert_equal("background: url(/logo-#{@logo_digest}.png);", output[:data])
43 | end
44 |
45 | def test_dependencies_are_tracked
46 | input = { environment: @env, data: 'background: url(logo.png);', filename: 'url2.css', metadata: {} }
47 | output = Sprockets::Rails::AssetUrlProcessor.call(input)
48 | assert_equal(1, output[:links].size)
49 | assert_equal(@logo_uri, output[:links].first)
50 | end
51 |
52 | def test_relative
53 | input = { environment: @env, data: 'background: url(./logo.png);', filename: 'url2.css', metadata: {} }
54 | output = Sprockets::Rails::AssetUrlProcessor.call(input)
55 | assert_equal("background: url(/logo-#{@logo_digest}.png);", output[:data])
56 | end
57 |
58 | def test_subdirectory
59 | input = { environment: @env, data: "background: url('jquery/jquery.js');", filename: 'url2.css', metadata: {} }
60 | output = Sprockets::Rails::AssetUrlProcessor.call(input)
61 | jquery_digest = 'c6910e1db4a5ed4905be728ab786471e81565f4a9d544734b199f3790de9f9a3'
62 | assert_equal("background: url(/jquery/jquery-#{jquery_digest}.js);", output[:data])
63 | end
64 |
65 | def test_protocol_relative_paths
66 | input = { environment: @env, data: "background: url(//assets.example.com/assets/fontawesome-webfont-82ff0fe46a6f60e0ab3c4a9891a0ae0a1f7b7e84c625f55358379177a2dcb202.eot);", filename: 'url2.css', metadata: {} }
67 | output = Sprockets::Rails::AssetUrlProcessor.call(input)
68 | assert_equal("background: url(//assets.example.com/assets/fontawesome-webfont-82ff0fe46a6f60e0ab3c4a9891a0ae0a1f7b7e84c625f55358379177a2dcb202.eot);", output[:data])
69 | end
70 | end
71 |
--------------------------------------------------------------------------------
/test/test_helper.rb:
--------------------------------------------------------------------------------
1 | require 'minitest/autorun'
2 |
3 | require 'action_view'
4 | require 'sprockets'
5 | # Apps generated before Rails 7.0 without rails/all require sprockets/railtie, not sprockets/rails
6 | # Same with other reverse dependencies like sassc-rails
7 | require 'sprockets/railtie'
8 | require 'sprockets/rails/context'
9 | require 'sprockets/rails/helper'
10 | require 'rails/version'
11 |
12 | ActiveSupport::TestCase.test_order = :random if ActiveSupport::TestCase.respond_to?(:test_order=)
13 |
14 | def append_media_attribute
15 | if ::Rails::VERSION::MAJOR < 7
16 | "media=\"screen\""
17 | end
18 | end
19 |
20 | class HelperTest < ActionView::TestCase
21 | FIXTURES_PATH = File.expand_path("../fixtures", __FILE__)
22 |
23 | def setup
24 | @assets = Sprockets::Environment.new
25 | @assets.append_path FIXTURES_PATH
26 | @assets.context_class.class_eval do
27 | include ::Sprockets::Rails::Context
28 | end
29 | tmp = File.expand_path("../../tmp", __FILE__)
30 | @manifest = Sprockets::Manifest.new(@assets, tmp)
31 |
32 | @view = ActionView::Base.new(ActionView::LookupContext.new([]), {}, nil)
33 | @view.extend ::Sprockets::Rails::Helper
34 | @view.assets_environment = @assets
35 | @view.assets_manifest = @manifest
36 | @view.resolve_assets_with = [ :manifest, :environment ]
37 | @view.assets_prefix = "/assets"
38 | @view.assets_precompile = %w( manifest.js )
39 | precompiled_assets = @manifest.find(@view.assets_precompile).map(&:logical_path)
40 | @view.check_precompiled_asset = true
41 | @view.unknown_asset_fallback = true
42 | @view.precompiled_asset_checker = -> logical_path { precompiled_assets.include? logical_path }
43 | @view.request = ActionDispatch::Request.new({
44 | "rack.url_scheme" => "https"
45 | })
46 |
47 | @assets.context_class.assets_prefix = @view.assets_prefix
48 | @assets.context_class.config = @view.config
49 |
50 | @foo_js_integrity = @assets['foo.js'].integrity
51 | @foo_css_integrity = @assets['foo.css'].integrity
52 | @bar_js_integrity = @assets['bar.js'].integrity
53 |
54 | @foo_js_digest = @assets['foo.js'].etag
55 | @foo_css_digest = @assets['foo.css'].etag
56 | @bar_js_digest = @assets['bar.js'].etag
57 | @bar_css_digest = @assets['bar.css'].etag
58 | @logo_digest = @assets['logo.png'].etag
59 |
60 | @foo_self_js_digest = @assets['foo.self.js'].etag
61 | @foo_self_css_digest = @assets['foo.self.css'].etag
62 | @bar_self_js_digest = @assets['bar.self.js'].etag
63 | @bar_self_css_digest = @assets['bar.self.css'].etag
64 |
65 | @foo_debug_js_digest = @assets['foo.debug.js'].etag
66 | @foo_debug_css_digest = @assets['foo.debug.css'].etag
67 | @bar_debug_js_digest = @assets['bar.debug.js'].etag
68 | @bar_debug_css_digest = @assets['bar.debug.css'].etag
69 |
70 | @dependency_js_digest = @assets['dependency.js'].etag
71 | @dependency_css_digest = @assets['dependency.css'].etag
72 | @file1_js_digest = @assets['file1.js'].etag
73 | @file1_css_digest = @assets['file1.css'].etag
74 | @file2_js_digest = @assets['file2.js'].etag
75 | @file2_css_digest = @assets['file2.css'].etag
76 |
77 | @dependency_self_js_digest = @assets['dependency.self.js'].etag
78 | @dependency_self_css_digest = @assets['dependency.self.css'].etag
79 | @file1_self_js_digest = @assets['file1.self.js'].etag
80 | @file1_self_css_digest = @assets['file1.self.css'].etag
81 | @file2_self_js_digest = @assets['file2.self.js'].etag
82 | @file2_self_css_digest = @assets['file2.self.css'].etag
83 |
84 | @dependency_debug_js_digest = @assets['dependency.debug.js'].etag
85 | @dependency_debug_css_digest = @assets['dependency.debug.css'].etag
86 | @file1_debug_js_digest = @assets['file1.debug.js'].etag
87 | @file1_debug_css_digest = @assets['file1.debug.css'].etag
88 | @file2_debug_js_digest = @assets['file2.debug.js'].etag
89 | @file2_debug_css_digest = @assets['file2.debug.css'].etag
90 | end
91 |
92 | def using_sprockets4?
93 | Gem::Version.new(Sprockets::VERSION) >= Gem::Version.new('4.x')
94 | end
95 |
96 | def test_foo_and_bar_different_digests
97 | refute_equal @foo_js_digest, @bar_js_digest
98 | refute_equal @foo_css_digest, @bar_css_digest
99 | end
100 |
101 | def assert_servable_asset_url(url)
102 | path, query = url.split("?", 2)
103 | path = path.sub(@view.assets_prefix, "")
104 |
105 | status = @assets.call({
106 | 'REQUEST_METHOD' => 'GET',
107 | 'PATH_INFO' => path,
108 | 'QUERY_STRING' => query
109 | })[0]
110 | assert_equal 200, status, "#{url} responded with #{status}"
111 | end
112 | end
113 |
114 | class NoHostHelperTest < HelperTest
115 | def test_javascript_include_tag
116 | Sprockets::Rails.deprecator.silence do
117 | assert_dom_equal %(),
118 | @view.javascript_include_tag("static")
119 | assert_dom_equal %(),
120 | @view.javascript_include_tag("static.js")
121 | assert_dom_equal %(),
122 | @view.javascript_include_tag(:static)
123 |
124 | assert_dom_equal %(),
125 | @view.javascript_include_tag("/elsewhere.js")
126 | assert_dom_equal %(\n),
127 | @view.javascript_include_tag("/script1.js", "script2.js")
128 |
129 | assert_dom_equal %(),
130 | @view.javascript_include_tag("http://example.com/script")
131 | assert_dom_equal %(),
132 | @view.javascript_include_tag("http://example.com/script.js")
133 | assert_dom_equal %(),
134 | @view.javascript_include_tag("//example.com/script.js")
135 |
136 | assert_dom_equal %(),
137 | @view.javascript_include_tag("static", :defer => "defer")
138 | assert_dom_equal %(),
139 | @view.javascript_include_tag("static", :async => "async")
140 | end
141 | end
142 |
143 | def test_stylesheet_link_tag
144 | Sprockets::Rails.deprecator.silence do
145 | assert_dom_equal %(),
146 | @view.stylesheet_link_tag("static")
147 | assert_dom_equal %(),
148 | @view.stylesheet_link_tag("static.css")
149 | assert_dom_equal %(),
150 | @view.stylesheet_link_tag(:static)
151 |
152 | assert_dom_equal %(),
153 | @view.stylesheet_link_tag("/elsewhere.css")
154 | assert_dom_equal %(\n),
155 | @view.stylesheet_link_tag("/style1.css", "style2.css")
156 |
157 | assert_dom_equal %(),
158 | @view.stylesheet_link_tag("http://www.example.com/styles/style")
159 | assert_dom_equal %(),
160 | @view.stylesheet_link_tag("http://www.example.com/styles/style.css")
161 | assert_dom_equal %(),
162 | @view.stylesheet_link_tag("//www.example.com/styles/style.css")
163 |
164 | assert_dom_equal %(),
165 | @view.stylesheet_link_tag("print", :media => "print")
166 | assert_dom_equal %(),
167 | @view.stylesheet_link_tag("print", :media => "")
168 | end
169 | end
170 |
171 | def test_javascript_include_tag_integrity
172 | Sprockets::Rails.deprecator.silence do
173 | assert_dom_equal %(),
174 | @view.javascript_include_tag("static", integrity: "sha-256-TvVUHzSfftWg1rcfL6TIJ0XKEGrgLyEq6lEpcmrG9qs=")
175 |
176 | assert_dom_equal %(),
177 | @view.javascript_include_tag("static", integrity: true)
178 | assert_dom_equal %(),
179 | @view.javascript_include_tag("static", integrity: false)
180 | assert_dom_equal %(),
181 | @view.javascript_include_tag("static", integrity: nil)
182 | end
183 | end
184 |
185 | def test_stylesheet_link_tag_integrity
186 | Sprockets::Rails.deprecator.silence do
187 | assert_dom_equal %(),
188 | @view.stylesheet_link_tag("static", integrity: "sha-256-5YzTQPuOJz/EpeXfN/+v1sxsjAj/dw8q26abiHZM3A4=")
189 |
190 | assert_dom_equal %(),
191 | @view.stylesheet_link_tag("static", integrity: true)
192 | assert_dom_equal %(),
193 | @view.stylesheet_link_tag("static", integrity: false)
194 | end
195 | end
196 |
197 | def test_javascript_path
198 | Sprockets::Rails.deprecator.silence do
199 | assert_equal "/javascripts/xmlhr.js", @view.javascript_path("xmlhr")
200 | assert_equal "/javascripts/xmlhr.js", @view.javascript_path("xmlhr.js")
201 | assert_equal "/javascripts/super/xmlhr.js", @view.javascript_path("super/xmlhr")
202 | assert_equal "/super/xmlhr.js", @view.javascript_path("/super/xmlhr")
203 |
204 | assert_equal "/javascripts/xmlhr.js?foo=1", @view.javascript_path("xmlhr.js?foo=1")
205 | assert_equal "/javascripts/xmlhr.js?foo=1", @view.javascript_path("xmlhr?foo=1")
206 | assert_equal "/javascripts/xmlhr.js#hash", @view.javascript_path("xmlhr.js#hash")
207 | assert_equal "/javascripts/xmlhr.js#hash", @view.javascript_path("xmlhr#hash")
208 | assert_equal "/javascripts/xmlhr.js?foo=1#hash", @view.javascript_path("xmlhr.js?foo=1#hash")
209 | end
210 | end
211 |
212 | def test_stylesheet_path
213 | Sprockets::Rails.deprecator.silence do
214 | assert_equal "/stylesheets/bank.css", @view.stylesheet_path("bank")
215 | assert_equal "/stylesheets/bank.css", @view.stylesheet_path("bank.css")
216 | assert_equal "/stylesheets/subdir/subdir.css", @view.stylesheet_path("subdir/subdir")
217 | assert_equal "/subdir/subdir.css", @view.stylesheet_path("/subdir/subdir.css")
218 |
219 | assert_equal "/stylesheets/bank.css?foo=1", @view.stylesheet_path("bank.css?foo=1")
220 | assert_equal "/stylesheets/bank.css?foo=1", @view.stylesheet_path("bank?foo=1")
221 | assert_equal "/stylesheets/bank.css#hash", @view.stylesheet_path("bank.css#hash")
222 | assert_equal "/stylesheets/bank.css#hash", @view.stylesheet_path("bank#hash")
223 | assert_equal "/stylesheets/bank.css?foo=1#hash", @view.stylesheet_path("bank.css?foo=1#hash")
224 | end
225 | end
226 | end
227 |
228 | class NoSSLHelperTest < NoHostHelperTest
229 | def setup
230 | super
231 |
232 | @view.request = nil
233 | end
234 |
235 | def test_javascript_include_tag_integrity
236 | Sprockets::Rails.deprecator.silence do
237 | assert_dom_equal %(),
238 | @view.javascript_include_tag("static", integrity: true)
239 | assert_dom_equal %(),
240 | @view.javascript_include_tag("static", integrity: false)
241 | assert_dom_equal %(),
242 | @view.javascript_include_tag("static", integrity: nil)
243 |
244 | assert_dom_equal %(),
245 | @view.javascript_include_tag("static", integrity: "sha-256-TvVUHzSfftWg1rcfL6TIJ0XKEGrgLyEq6lEpcmrG9qs=")
246 | end
247 |
248 | assert_dom_equal %(),
249 | @view.javascript_include_tag("foo", integrity: true)
250 | end
251 |
252 | def test_stylesheet_link_tag_integrity
253 | Sprockets::Rails.deprecator.silence do
254 | assert_dom_equal %(),
255 | @view.stylesheet_link_tag("static", integrity: true)
256 | assert_dom_equal %(),
257 | @view.stylesheet_link_tag("static", integrity: false)
258 | assert_dom_equal %(),
259 | @view.stylesheet_link_tag("static", integrity: nil)
260 |
261 | assert_dom_equal %(),
262 | @view.stylesheet_link_tag("static", integrity: "sha-256-5YzTQPuOJz/EpeXfN/+v1sxsjAj/dw8q26abiHZM3A4=")
263 | end
264 |
265 | assert_dom_equal %(),
266 | @view.stylesheet_link_tag("foo", integrity: true)
267 | end
268 | end
269 |
270 | class LocalhostHelperTest < NoHostHelperTest
271 | def setup
272 | super
273 |
274 | @view.request = ActionDispatch::Request.new({
275 | "rack.url_scheme" => "http",
276 | "REMOTE_ADDR" => "127.0.0.1"
277 | })
278 | end
279 |
280 | def test_javascript_include_tag_integrity
281 | super
282 |
283 | assert_dom_equal %(),
284 | @view.javascript_include_tag("foo", integrity: false)
285 | assert_dom_equal %(),
286 | @view.javascript_include_tag("foo", integrity: nil)
287 |
288 | assert_dom_equal %(),
289 | @view.javascript_include_tag("foo", integrity: true)
290 | assert_dom_equal %(),
291 | @view.javascript_include_tag("foo.js", integrity: true)
292 | assert_dom_equal %(),
293 | @view.javascript_include_tag(:foo, integrity: true)
294 |
295 | assert_dom_equal %(\n),
296 | @view.javascript_include_tag(:foo, :bar, integrity: true)
297 | end
298 |
299 | def test_stylesheet_link_tag_integrity
300 | super
301 |
302 | assert_dom_equal %(),
303 | @view.stylesheet_link_tag("foo", integrity: false)
304 | assert_dom_equal %(),
305 | @view.stylesheet_link_tag("foo", integrity: nil)
306 |
307 | assert_dom_equal %(),
308 | @view.stylesheet_link_tag("foo", integrity: true)
309 | assert_dom_equal %(),
310 | @view.stylesheet_link_tag("foo.css", integrity: true)
311 | assert_dom_equal %(),
312 | @view.stylesheet_link_tag(:foo, integrity: true)
313 |
314 | assert_dom_equal %(\n),
315 | @view.stylesheet_link_tag(:foo, :bar, integrity: true)
316 | end
317 | end
318 |
319 | class RelativeHostHelperTest < HelperTest
320 | def setup
321 | super
322 |
323 | @view.config.asset_host = "assets.example.com"
324 | end
325 |
326 | def test_javascript_path
327 | Sprockets::Rails.deprecator.silence do
328 | assert_equal "https://assets.example.com/javascripts/xmlhr.js", @view.javascript_path("xmlhr")
329 | assert_equal "https://assets.example.com/javascripts/xmlhr.js", @view.javascript_path("xmlhr.js")
330 | assert_equal "https://assets.example.com/javascripts/super/xmlhr.js", @view.javascript_path("super/xmlhr")
331 | assert_equal "https://assets.example.com/super/xmlhr.js", @view.javascript_path("/super/xmlhr")
332 |
333 | assert_equal "https://assets.example.com/javascripts/xmlhr.js?foo=1", @view.javascript_path("xmlhr.js?foo=1")
334 | assert_equal "https://assets.example.com/javascripts/xmlhr.js?foo=1", @view.javascript_path("xmlhr?foo=1")
335 | assert_equal "https://assets.example.com/javascripts/xmlhr.js#hash", @view.javascript_path("xmlhr.js#hash")
336 | assert_equal "https://assets.example.com/javascripts/xmlhr.js#hash", @view.javascript_path("xmlhr#hash")
337 | assert_equal "https://assets.example.com/javascripts/xmlhr.js?foo=1#hash", @view.javascript_path("xmlhr.js?foo=1#hash")
338 | end
339 |
340 | assert_dom_equal %(),
341 | @view.javascript_include_tag("foo")
342 | assert_dom_equal %(),
343 | @view.javascript_include_tag("foo.js")
344 | assert_dom_equal %(),
345 | @view.javascript_include_tag(:foo)
346 | end
347 |
348 | def test_stylesheet_path
349 | Sprockets::Rails.deprecator.silence do
350 | assert_equal "https://assets.example.com/stylesheets/bank.css", @view.stylesheet_path("bank")
351 | assert_equal "https://assets.example.com/stylesheets/bank.css", @view.stylesheet_path("bank.css")
352 | assert_equal "https://assets.example.com/stylesheets/subdir/subdir.css", @view.stylesheet_path("subdir/subdir")
353 | assert_equal "https://assets.example.com/subdir/subdir.css", @view.stylesheet_path("/subdir/subdir.css")
354 |
355 | assert_equal "https://assets.example.com/stylesheets/bank.css?foo=1", @view.stylesheet_path("bank.css?foo=1")
356 | assert_equal "https://assets.example.com/stylesheets/bank.css?foo=1", @view.stylesheet_path("bank?foo=1")
357 | assert_equal "https://assets.example.com/stylesheets/bank.css#hash", @view.stylesheet_path("bank.css#hash")
358 | assert_equal "https://assets.example.com/stylesheets/bank.css#hash", @view.stylesheet_path("bank#hash")
359 | assert_equal "https://assets.example.com/stylesheets/bank.css?foo=1#hash", @view.stylesheet_path("bank.css?foo=1#hash")
360 | end
361 |
362 | assert_dom_equal %(),
363 | @view.stylesheet_link_tag("foo")
364 | assert_dom_equal %(),
365 | @view.stylesheet_link_tag("foo.css")
366 | assert_dom_equal %(),
367 | @view.stylesheet_link_tag(:foo)
368 | end
369 |
370 | def test_asset_url
371 | assert_equal "var url = '//assets.example.com/assets/foo.js';\n", @assets["url.js"].to_s
372 | assert_equal "p { background: url(//assets.example.com/assets/logo.png); }\n", @assets["url.css"].to_s
373 | end
374 | end
375 |
376 | class NoDigestHelperTest < NoHostHelperTest
377 | def setup
378 | super
379 | @view.digest_assets = false
380 | @assets.context_class.digest_assets = false
381 | end
382 |
383 | def test_javascript_include_tag
384 | super
385 |
386 | assert_dom_equal %(),
387 | @view.javascript_include_tag("foo")
388 | assert_dom_equal %(),
389 | @view.javascript_include_tag("foo.js")
390 | assert_dom_equal %(),
391 | @view.javascript_include_tag(:foo)
392 |
393 | assert_servable_asset_url "/assets/foo.js"
394 | end
395 |
396 | def test_stylesheet_link_tag
397 | super
398 |
399 | assert_dom_equal %(),
400 | @view.stylesheet_link_tag("foo")
401 | assert_dom_equal %(),
402 | @view.stylesheet_link_tag("foo.css")
403 | assert_dom_equal %(),
404 | @view.stylesheet_link_tag(:foo)
405 |
406 | assert_servable_asset_url "/assets/foo.css"
407 | end
408 |
409 | def test_javascript_path
410 | super
411 |
412 | assert_equal "/assets/foo.js", @view.javascript_path("foo")
413 | assert_servable_asset_url "/assets/foo.js"
414 | end
415 |
416 | def test_stylesheet_path
417 | super
418 |
419 | assert_equal "/assets/foo.css", @view.stylesheet_path("foo")
420 | assert_servable_asset_url "/assets/foo.css"
421 | end
422 |
423 | def test_asset_url
424 | assert_equal "var url = '/assets/foo.js';\n", @assets["url.js"].to_s
425 | assert_equal "p { background: url(/assets/logo.png); }\n", @assets["url.css"].to_s
426 | end
427 | end
428 |
429 | class DigestHelperTest < NoHostHelperTest
430 | def setup
431 | super
432 | @view.digest_assets = true
433 | @assets.context_class.digest_assets = true
434 | end
435 |
436 | def test_javascript_include_tag
437 | super
438 |
439 | assert_dom_equal %(),
440 | @view.javascript_include_tag("foo")
441 | assert_dom_equal %(),
442 | @view.javascript_include_tag("foo.js")
443 | assert_dom_equal %(),
444 | @view.javascript_include_tag(:foo)
445 |
446 | assert_dom_equal %(\n),
447 | @view.javascript_include_tag(:foo, :bar)
448 |
449 | assert_servable_asset_url "/assets/foo-#{@foo_js_digest}.js"
450 | end
451 |
452 | def test_stylesheet_link_tag
453 | super
454 |
455 | assert_dom_equal %(),
456 | @view.stylesheet_link_tag("foo")
457 | assert_dom_equal %(),
458 | @view.stylesheet_link_tag("foo.css")
459 | assert_dom_equal %(),
460 | @view.stylesheet_link_tag(:foo)
461 |
462 | assert_dom_equal %(\n),
463 | @view.stylesheet_link_tag(:foo, :bar)
464 |
465 | assert_servable_asset_url "/assets/foo-#{@foo_css_digest}.css"
466 | end
467 |
468 | def test_javascript_include_tag_integrity
469 | super
470 |
471 | assert_dom_equal %(),
472 | @view.javascript_include_tag("foo", integrity: false)
473 | assert_dom_equal %(),
474 | @view.javascript_include_tag("foo", integrity: nil)
475 |
476 | assert_dom_equal %(),
477 | @view.javascript_include_tag("foo", integrity: true)
478 | assert_dom_equal %(),
479 | @view.javascript_include_tag("foo.js", integrity: true)
480 | assert_dom_equal %(),
481 | @view.javascript_include_tag(:foo, integrity: true)
482 |
483 | assert_dom_equal %(\n),
484 | @view.javascript_include_tag(:foo, :bar, integrity: true)
485 | end
486 |
487 | def test_stylesheet_link_tag_integrity
488 | super
489 |
490 | assert_dom_equal %(),
491 | @view.stylesheet_link_tag("foo", integrity: false)
492 | assert_dom_equal %(),
493 | @view.stylesheet_link_tag("foo", integrity: nil)
494 |
495 | assert_dom_equal %(),
496 | @view.stylesheet_link_tag("foo", integrity: true)
497 | assert_dom_equal %(),
498 | @view.stylesheet_link_tag("foo.css", integrity: true)
499 | assert_dom_equal %(),
500 | @view.stylesheet_link_tag(:foo, integrity: true)
501 |
502 | assert_dom_equal %(\n),
503 | @view.stylesheet_link_tag(:foo, :bar, integrity: true)
504 | end
505 |
506 | def test_javascript_path
507 | super
508 |
509 | assert_equal "/assets/foo-#{@foo_js_digest}.js", @view.javascript_path("foo")
510 | assert_servable_asset_url "/assets/foo-#{@foo_js_digest}.js"
511 | end
512 |
513 | def test_stylesheet_path
514 | super
515 |
516 | assert_equal "/assets/foo-#{@foo_css_digest}.css", @view.stylesheet_path("foo")
517 | assert_servable_asset_url "/assets/foo-#{@foo_css_digest}.css"
518 | end
519 |
520 | def test_asset_digest_path
521 | assert_equal "foo-#{@foo_js_digest}.js", @view.asset_digest_path("foo.js")
522 | assert_equal "foo-#{@foo_css_digest}.css", @view.asset_digest_path("foo.css")
523 | end
524 |
525 | def test_asset_url
526 | assert_equal "var url = '/assets/foo-#{@foo_js_digest}.js';\n", @assets["url.js"].to_s
527 | assert_equal "p { background: url(/assets/logo-#{@logo_digest}.png); }\n", @assets["url.css"].to_s
528 | end
529 | end
530 |
531 | class DebugHelperTest < NoHostHelperTest
532 | def setup
533 | super
534 | @view.debug_assets = true
535 | end
536 |
537 | def test_javascript_include_tag
538 | super
539 |
540 | if using_sprockets4?
541 | assert_dom_equal %(),
542 | @view.javascript_include_tag(:foo)
543 | assert_dom_equal %(),
544 | @view.javascript_include_tag(:bar)
545 | assert_dom_equal %(\n),
546 | @view.javascript_include_tag(:file1, :file2)
547 |
548 | assert_servable_asset_url "/assets/foo.debug.js"
549 | assert_servable_asset_url "/assets/bar.debug.js"
550 | assert_servable_asset_url "/assets/dependency.debug.js"
551 | assert_servable_asset_url "/assets/file1.debug.js"
552 | assert_servable_asset_url "/assets/file2.debug.js"
553 | else
554 | assert_dom_equal %(),
555 | @view.javascript_include_tag(:foo)
556 | assert_dom_equal %(\n),
557 | @view.javascript_include_tag(:bar)
558 | assert_dom_equal %(\n\n),
559 | @view.javascript_include_tag(:file1, :file2)
560 |
561 | assert_servable_asset_url "/assets/foo.self.js?body=1"
562 | assert_servable_asset_url "/assets/bar.self.js?body=1"
563 | assert_servable_asset_url "/assets/dependency.self.js?body=1"
564 | assert_servable_asset_url "/assets/file1.self.js?body=1"
565 | assert_servable_asset_url "/assets/file2.self.js?body=1"
566 | end
567 | end
568 |
569 | def test_stylesheet_link_tag
570 | super
571 |
572 | if using_sprockets4?
573 | assert_dom_equal %(),
574 | @view.stylesheet_link_tag(:foo)
575 | assert_dom_equal %(),
576 | @view.stylesheet_link_tag(:bar)
577 | assert_dom_equal %(\n),
578 | @view.stylesheet_link_tag(:file1, :file2)
579 |
580 | assert_servable_asset_url "/assets/foo.self.css"
581 | assert_servable_asset_url "/assets/bar.self.css"
582 | assert_servable_asset_url "/assets/dependency.self.css"
583 | assert_servable_asset_url "/assets/file1.self.css"
584 | assert_servable_asset_url "/assets/file2.self.css"
585 | else
586 | assert_dom_equal %(),
587 | @view.stylesheet_link_tag(:foo)
588 | assert_dom_equal %(\n),
589 | @view.stylesheet_link_tag(:bar)
590 | assert_dom_equal %(\n\n),
591 | @view.stylesheet_link_tag(:file1, :file2)
592 |
593 | assert_servable_asset_url "/assets/foo.self.css?body=1"
594 | assert_servable_asset_url "/assets/bar.self.css?body=1"
595 | assert_servable_asset_url "/assets/dependency.self.css?body=1"
596 | assert_servable_asset_url "/assets/file1.self.css?body=1"
597 | assert_servable_asset_url "/assets/file2.self.css?body=1"
598 | end
599 | end
600 |
601 | def test_javascript_path
602 | super
603 |
604 | assert_equal "/assets/foo.js", @view.javascript_path("foo")
605 | assert_servable_asset_url "/assets/foo.js"
606 | end
607 |
608 | def test_stylesheet_path
609 | super
610 |
611 | assert_equal "/assets/foo.css", @view.stylesheet_path("foo")
612 | assert_servable_asset_url "/assets/foo.css"
613 | end
614 | end
615 |
616 | class DebugDigestHelperTest < NoHostHelperTest
617 | def setup
618 | super
619 | @view.debug_assets = true
620 | @view.digest_assets = true
621 | @assets.context_class.digest_assets = true
622 | end
623 |
624 | def test_javascript_include_tag
625 | super
626 |
627 | if using_sprockets4?
628 | assert_dom_equal %(),
629 | @view.javascript_include_tag(:foo)
630 | assert_dom_equal %(),
631 | @view.javascript_include_tag(:bar)
632 | assert_dom_equal %(\n),
633 | @view.javascript_include_tag(:file1, :file2)
634 |
635 | assert_servable_asset_url "/assets/foo.debug-#{@foo_debug_js_digest}.js"
636 | assert_servable_asset_url "/assets/bar.debug-#{@bar_debug_js_digest}.js"
637 | assert_servable_asset_url "/assets/dependency.debug-#{@dependency_debug_js_digest}.js"
638 | assert_servable_asset_url "/assets/file1.debug-#{@file1_debug_js_digest}.js"
639 | assert_servable_asset_url "/assets/file2.debug-#{@file2_debug_js_digest}.js"
640 | else
641 | assert_dom_equal %(),
642 | @view.javascript_include_tag(:foo)
643 | assert_dom_equal %(\n),
644 | @view.javascript_include_tag(:bar)
645 | assert_dom_equal %(\n\n),
646 | @view.javascript_include_tag(:file1, :file2)
647 |
648 | assert_servable_asset_url "/assets/foo.self-#{@foo_self_js_digest}.js?body=1"
649 | assert_servable_asset_url "/assets/bar.self-#{@bar_self_js_digest}.js?body=1"
650 | assert_servable_asset_url "/assets/dependency.self-#{@dependency_self_js_digest}.js?body=1"
651 | assert_servable_asset_url "/assets/file1.self-#{@file1_self_js_digest}.js?body=1"
652 | assert_servable_asset_url "/assets/file2.self-#{@file2_self_js_digest}.js?body=1"
653 | end
654 | end
655 |
656 | def test_stylesheet_link_tag
657 | super
658 |
659 | if using_sprockets4?
660 | assert_dom_equal %(),
661 | @view.stylesheet_link_tag(:foo)
662 | assert_dom_equal %(),
663 | @view.stylesheet_link_tag(:bar)
664 | assert_dom_equal %(\n),
665 | @view.stylesheet_link_tag(:file1, :file2)
666 |
667 | assert_servable_asset_url "/assets/foo.self-#{@foo_self_css_digest}.css"
668 | assert_servable_asset_url "/assets/bar.self-#{@bar_self_css_digest}.css"
669 | assert_servable_asset_url "/assets/dependency.self-#{@dependency_self_css_digest}.css"
670 | assert_servable_asset_url "/assets/file1.self-#{@file1_self_css_digest}.css"
671 | assert_servable_asset_url "/assets/file2.self-#{@file2_self_css_digest}.css"
672 | else
673 | assert_dom_equal %(),
674 | @view.stylesheet_link_tag(:foo)
675 | assert_dom_equal %(\n),
676 | @view.stylesheet_link_tag(:bar)
677 | assert_dom_equal %(\n\n),
678 | @view.stylesheet_link_tag(:file1, :file2)
679 |
680 | assert_servable_asset_url "/assets/foo.self-#{@foo_self_css_digest}.css?body=1"
681 | assert_servable_asset_url "/assets/bar.self-#{@bar_self_css_digest}.css?body=1"
682 | assert_servable_asset_url "/assets/dependency.self-#{@dependency_self_css_digest}.css?body=1"
683 | assert_servable_asset_url "/assets/file1.self-#{@file1_self_css_digest}.css?body=1"
684 | assert_servable_asset_url "/assets/file2.self-#{@file2_self_css_digest}.css?body=1"
685 | end
686 | end
687 |
688 | def test_javascript_path
689 | super
690 |
691 | assert_equal "/assets/foo-#{@foo_js_digest}.js", @view.javascript_path("foo")
692 | assert_servable_asset_url "/assets/foo-#{@foo_js_digest}.js"
693 | end
694 |
695 | def test_stylesheet_path
696 | super
697 |
698 | assert_equal "/assets/foo-#{@foo_css_digest}.css", @view.stylesheet_path("foo")
699 | assert_servable_asset_url "/assets/foo-#{@foo_css_digest}.css"
700 | end
701 |
702 | def test_asset_digest_path
703 | assert_equal "foo-#{@foo_js_digest}.js", @view.asset_digest_path("foo.js")
704 | assert_equal "foo-#{@foo_css_digest}.css", @view.asset_digest_path("foo.css")
705 | end
706 |
707 | def test_asset_url
708 | assert_equal "var url = '/assets/foo-#{@foo_js_digest}.js';\n", @assets["url.js"].to_s
709 | assert_equal "p { background: url(/assets/logo-#{@logo_digest}.png); }\n", @assets["url.css"].to_s
710 | end
711 | end
712 |
713 | class ManifestHelperTest < NoHostHelperTest
714 | def setup
715 | super
716 |
717 | @manifest = Sprockets::Manifest.new(@assets, FIXTURES_PATH)
718 | @manifest.assets["foo.js"] = "foo-#{@foo_js_digest}.js"
719 | @manifest.assets["foo.css"] = "foo-#{@foo_css_digest}.css"
720 |
721 | @manifest.files["foo-#{@foo_js_digest}.js"] = { "integrity" => @foo_js_integrity }
722 | @manifest.files["foo-#{@foo_css_digest}.css"] = { "integrity" => @foo_css_integrity }
723 |
724 | @view.digest_assets = true
725 | @view.assets_environment = nil
726 | @view.assets_manifest = @manifest
727 | @view.resolve_assets_with = [ :manifest ]
728 | end
729 |
730 | def test_javascript_include_tag
731 | super
732 |
733 | assert_dom_equal %(),
734 | @view.javascript_include_tag("foo")
735 | assert_dom_equal %(),
736 | @view.javascript_include_tag("foo.js")
737 | assert_dom_equal %(),
738 | @view.javascript_include_tag(:foo)
739 | end
740 |
741 | def test_stylesheet_link_tag
742 | super
743 |
744 | assert_dom_equal %(),
745 | @view.stylesheet_link_tag("foo")
746 | assert_dom_equal %(),
747 | @view.stylesheet_link_tag("foo.css")
748 | assert_dom_equal %(),
749 | @view.stylesheet_link_tag(:foo)
750 | end
751 |
752 | def test_javascript_include_tag_integrity
753 | super
754 |
755 | assert_dom_equal %(),
756 | @view.javascript_include_tag("foo", integrity: true)
757 | assert_dom_equal %(),
758 | @view.javascript_include_tag("foo.js", integrity: true)
759 | assert_dom_equal %(),
760 | @view.javascript_include_tag(:foo, integrity: true)
761 | end
762 |
763 | def test_stylesheet_link_tag_integrity
764 | super
765 |
766 | assert_dom_equal %(),
767 | @view.stylesheet_link_tag("foo", integrity: true)
768 | assert_dom_equal %(),
769 | @view.stylesheet_link_tag("foo.css", integrity: true)
770 | assert_dom_equal %(),
771 | @view.stylesheet_link_tag(:foo, integrity: true)
772 | end
773 |
774 | def test_javascript_path
775 | super
776 |
777 | assert_equal "/assets/foo-#{@foo_js_digest}.js", @view.javascript_path("foo")
778 | end
779 |
780 | def test_stylesheet_path
781 | super
782 |
783 | assert_equal "/assets/foo-#{@foo_css_digest}.css", @view.stylesheet_path("foo")
784 | end
785 |
786 | def test_asset_digest_path
787 | assert_equal "foo-#{@foo_js_digest}.js", @view.asset_digest_path("foo.js")
788 | assert_equal "foo-#{@foo_css_digest}.css", @view.asset_digest_path("foo.css")
789 | end
790 |
791 | def test_assets_environment_unavailable
792 | refute @view.assets_environment
793 | end
794 | end
795 |
796 | class DebugManifestHelperTest < ManifestHelperTest
797 | def setup
798 | super
799 |
800 | @view.debug_assets = true
801 | end
802 |
803 | def test_javascript_include_tag_integrity
804 | pass
805 | end
806 |
807 | def test_stylesheet_link_tag_integrity
808 | pass
809 | end
810 | end
811 |
812 | class AssetResolverOrderingTest < HelperTest
813 | def setup
814 | super
815 |
816 | @view.digest_assets = true
817 |
818 | @view.assets_manifest = Sprockets::Manifest.new(@assets, FIXTURES_PATH).tap do |stale|
819 | stale.assets["foo.js"] = "foo-stale.js"
820 | stale.files["foo-stale.js"] = { "integrity" => "stale-manifest" }
821 |
822 | stale.assets["foo.css"] = "foo-stale.css"
823 | stale.files["foo-stale.css"] = { "integrity" => "stale-manifest" }
824 | end
825 | end
826 |
827 | def test_digest_prefers_asset_environment_over_manifest
828 | @view.resolve_assets_with = [ :environment, :manifest ]
829 |
830 | assert_equal "foo-#{@foo_js_digest}.js", @view.asset_digest_path("foo.js")
831 | assert_equal "foo-#{@foo_css_digest}.css", @view.asset_digest_path("foo.css")
832 |
833 | assert_equal @foo_js_integrity, @view.asset_integrity("foo.js")
834 | assert_equal @foo_css_integrity, @view.asset_integrity("foo.css")
835 | end
836 |
837 | def test_try_resolvers_until_first_result
838 | @view.resolve_assets_with = [ :manifest, :environment ]
839 |
840 | assert_equal 'foo-stale.js', @view.asset_digest_path('foo.js')
841 | assert_equal "bar-#{@bar_js_digest}.js", @view.asset_digest_path('bar.js')
842 | assert_nil @view.asset_digest_path('nonexistent')
843 |
844 | assert_equal 'stale-manifest', @view.asset_integrity('foo.js')
845 | assert_equal @bar_js_integrity, @view.asset_integrity('bar.js')
846 | assert_nil @view.asset_integrity('nonexistent')
847 | end
848 |
849 | def test_obeys_asset_resolver_order
850 | @view.resolve_assets_with = []
851 | assert_nil @view.asset_digest_path('foo.js')
852 | assert_nil @view.asset_integrity('foo.js')
853 | end
854 | end
855 |
856 | class AssetUrlHelperLinksTarget < HelperTest
857 | def test_precompile_allows_links
858 | @view.assets_precompile = ["url.css"]
859 | precompiled_assets = @manifest.find(@view.assets_precompile).map(&:logical_path)
860 | @view.precompiled_asset_checker = -> logical_path { precompiled_assets.include? logical_path }
861 | assert @view.asset_path("url.css")
862 | assert @view.asset_path("logo.png")
863 |
864 | assert_raises(Sprockets::Rails::Helper::AssetNotPrecompiled) do
865 | @view.asset_path("foo.css")
866 | end
867 | end
868 |
869 | def test_links_image_target
870 | assert_match "logo.png", @assets['url.css'].links.to_a[0]
871 | end
872 |
873 | def test_doesnt_track_public_assets
874 | refute_match "does_not_exist.png", @assets['error/missing.css'].links.to_a[0]
875 | end
876 |
877 | def test_asset_environment_reference_is_cached
878 | env = @view.assets_environment
879 | assert_kind_of Sprockets::CachedEnvironment, env
880 | assert @view.assets_environment.equal?(env), "view didn't return the same cached instance"
881 | end
882 | end
883 |
884 | class PrecompiledAssetHelperTest < HelperTest
885 | def setup
886 | super
887 | @bundle_js_name = '/assets/bundle.js'
888 | end
889 |
890 | # both subclass and more specific error are supported due to
891 | # https://github.com/rails/sprockets-rails/pull/414/commits/760a805a9f56d3df0d4b83bd4a5a6476eb3aeb29
892 | def test_javascript_precompile
893 | assert_raises(Sprockets::Rails::Helper::AssetNotPrecompiled) do
894 | @view.javascript_include_tag("not_precompiled")
895 | end
896 | end
897 |
898 | def test_javascript_precompile_throws_the_descriptive_error
899 | assert_raises(Sprockets::Rails::Helper::AssetNotPrecompiledError) do
900 | @view.javascript_include_tag("not_precompiled")
901 | end
902 | end
903 |
904 | def test_stylesheet_precompile
905 | assert_raises(Sprockets::Rails::Helper::AssetNotPrecompiled) do
906 | @view.stylesheet_link_tag("not_precompiled")
907 | end
908 | end
909 |
910 | def test_index_files
911 | assert_dom_equal %(),
912 | @view.javascript_include_tag("bundle")
913 | end
914 | end
915 |
916 | class DeprecationTest < HelperTest
917 | def test_deprecations_for_asset_path
918 | @view.send(:define_singleton_method, :public_compute_asset_path, -> {})
919 | assert_deprecated("use the `skip_pipeline: true` option", Sprockets::Rails.deprecator) do
920 | @view.asset_path("does_not_exist.noextension")
921 | end
922 | ensure
923 | @view.instance_eval('undef :public_compute_asset_path')
924 | end
925 |
926 | def test_deprecations_for_asset_url
927 | @view.send(:define_singleton_method, :public_compute_asset_path, -> {})
928 |
929 | assert_deprecated("use the `skip_pipeline: true` option", Sprockets::Rails.deprecator) do
930 | @view.asset_url("does_not_exist.noextension")
931 | end
932 | ensure
933 | @view.instance_eval('undef :public_compute_asset_path')
934 | end
935 |
936 | def test_deprecations_for_image_tag
937 | @view.send(:define_singleton_method, :public_compute_asset_path, -> {})
938 |
939 | assert_deprecated("use the `skip_pipeline: true` option", Sprockets::Rails.deprecator) do
940 | @view.image_tag("does_not_exist.noextension")
941 | end
942 | ensure
943 | @view.instance_eval('undef :public_compute_asset_path')
944 | end
945 | end
946 |
947 | class RaiseUnlessPrecompiledAssetDisabledTest < HelperTest
948 | def test_check_precompiled_asset_enabled
949 | @view.check_precompiled_asset = true
950 | assert_raises(Sprockets::Rails::Helper::AssetNotPrecompiled) do
951 | @view.asset_path("not_precompiled.css")
952 | end
953 | end
954 |
955 | def test_check_precompiled_asset_disabled
956 | @view.check_precompiled_asset = false
957 | assert @view.asset_path("not_precompiled.css")
958 | end
959 | end
960 |
961 | class PrecompiledDebugAssetHelperTest < PrecompiledAssetHelperTest
962 |
963 | # Re-run all PrecompiledAssetHelperTest with a different setup
964 | def setup
965 | super
966 | @view.debug_assets = true
967 | if using_sprockets4?
968 | @bundle_js_name = '/assets/bundle.debug.js'
969 | else
970 | @bundle_js_name = '/assets/bundle/index.self.js?body=1'
971 | end
972 | end
973 | end
974 |
--------------------------------------------------------------------------------
/test/test_quiet_assets.rb:
--------------------------------------------------------------------------------
1 | require 'active_support'
2 | require 'active_support/testing/isolation'
3 | require 'active_support/log_subscriber/test_helper'
4 | require 'minitest/autorun'
5 |
6 | require 'sprockets/railtie'
7 | require 'rails'
8 |
9 | Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
10 |
11 | class TestQuietAssets < Minitest::Test
12 | include ActiveSupport::Testing::Isolation
13 |
14 | ROOT_PATH = Pathname.new(File.expand_path("../../tmp/app", __FILE__))
15 | ASSET_PATH = ROOT_PATH.join("app","assets", "config")
16 |
17 | def setup
18 | FileUtils.mkdir_p(ROOT_PATH)
19 | Dir.chdir(ROOT_PATH)
20 |
21 | @app = Class.new(Rails::Application)
22 | @app.config.eager_load = false
23 | @app.config.logger = ActiveSupport::Logger.new("/dev/null")
24 | @app.config.active_support.to_time_preserves_timezone = :zone
25 |
26 | FileUtils.mkdir_p(ASSET_PATH)
27 | File.open(ASSET_PATH.join("manifest.js"), "w") { |f| f << "" }
28 |
29 | @app.initialize!
30 |
31 | Rails.logger.level = Logger::DEBUG
32 | end
33 |
34 | def test_silences_with_default_prefix
35 | assert_equal Logger::ERROR, middleware.call("PATH_INFO" => "/assets/stylesheets/application.css")
36 | end
37 |
38 | def test_silences_with_custom_prefix
39 | Rails.application.config.assets.prefix = "path/to"
40 | assert_equal Logger::ERROR, middleware.call("PATH_INFO" => "/path/to/thing")
41 | end
42 |
43 | def test_does_not_silence_without_match
44 | assert_equal Logger::DEBUG, middleware.call("PATH_INFO" => "/path/to/thing")
45 | end
46 |
47 | def test_logger_does_not_respond_to_silence
48 | ::Rails.logger.stub :respond_to?, false do
49 | assert_raises(Sprockets::Rails::LoggerSilenceError) { middleware.call("PATH_INFO" => "/assets/stylesheets/application.css") }
50 | end
51 | end
52 |
53 | private
54 |
55 | def middleware
56 | @middleware ||= Sprockets::Rails::QuietAssets.new(->(env) { Rails.logger.level })
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/test/test_railtie.rb:
--------------------------------------------------------------------------------
1 | require 'active_support'
2 | require 'active_support/testing/isolation'
3 | require 'minitest/autorun'
4 |
5 | Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
6 |
7 | def silence_stderr
8 | orig_stderr = $stderr.clone
9 | $stderr.reopen File.new('/dev/null', 'w')
10 | yield
11 | ensure
12 | $stderr.reopen orig_stderr
13 | end
14 |
15 | class TestBoot < Minitest::Test
16 | include ActiveSupport::Testing::Isolation
17 |
18 | ROOT = File.expand_path("../../tmp/app", __FILE__)
19 | FIXTURES_PATH = File.expand_path("../fixtures", __FILE__)
20 |
21 | attr_reader :app
22 |
23 | def setup
24 | require 'rails'
25 | # Can't seem to get initialize to run w/o this
26 | require 'action_controller/railtie'
27 | require 'active_support/dependencies'
28 | require 'tzinfo'
29 |
30 | ENV['RAILS_ENV'] = 'test'
31 |
32 | FileUtils.mkdir_p ROOT
33 | Dir.chdir ROOT
34 |
35 | @app = Class.new(Rails::Application)
36 | @app.config.eager_load = false
37 | @app.config.time_zone = 'UTC'
38 | @app.config.middleware ||= Rails::Configuration::MiddlewareStackProxy.new
39 | @app.config.active_support.deprecation = :notify
40 |
41 | Dir.chdir(app.root) do
42 | dir = "app/assets/config"
43 | FileUtils.mkdir_p(dir)
44 | File.open("#{ dir }/manifest.js", "w") do |f|
45 | f << ""
46 | end
47 | end
48 | end
49 |
50 | def test_initialize
51 | app.initialize!
52 | end
53 | end
54 |
55 | class TestRailtie < TestBoot
56 | def setup
57 | require 'sprockets/railtie'
58 | super
59 |
60 | # sprockets-4.0.0.beta8 does not like 'rake assets:clobber' when this directory does not exist
61 | Dir.chdir(app.root) do
62 | dir = "tmp/cache/assets/sprockets"
63 | FileUtils.mkdir_p(dir)
64 | end
65 | end
66 |
67 | def test_defaults_to_compile_assets_with_env_and_manifest_available
68 | assert_equal true, app.config.assets.compile
69 |
70 | app.initialize!
71 |
72 | # Env is available
73 | refute_nil env = app.assets
74 | assert_kind_of Sprockets::Environment, env
75 |
76 | # Manifest is always available
77 | assert manifest = app.assets_manifest
78 | assert_equal app.assets, manifest.environment
79 | assert_equal File.join(ROOT, "public/assets"), manifest.dir
80 |
81 | # Resolves against manifest then environment by default
82 | assert_equal [ :manifest, :environment ], app.config.assets.resolve_with
83 |
84 | # Sprockets config
85 | assert_equal ROOT, env.root
86 | assert_equal "", env.version
87 | assert env.cache
88 | assert_includes(env.paths, "#{ROOT}/app/assets/config")
89 |
90 | assert_nil env.js_compressor
91 | assert_nil env.css_compressor
92 | end
93 |
94 | def test_disabling_compile_has_manifest_but_no_env
95 | app.configure do
96 | config.assets.compile = false
97 | end
98 |
99 | assert_equal false, app.config.assets.compile
100 |
101 | app.initialize!
102 |
103 | # No env when compile is disabled
104 | assert_nil app.assets
105 |
106 | # Manifest is always available
107 | refute_nil manifest = app.assets_manifest
108 | assert_nil manifest.environment
109 | assert_equal File.join(ROOT, "public/assets"), manifest.dir
110 |
111 | # Resolves against manifest only
112 | assert_equal [ :manifest ], app.config.assets.resolve_with
113 | end
114 |
115 | def test_enabling_debug_resolves_with_env_only
116 | app.configure do
117 | config.assets.debug = true
118 | end
119 |
120 | assert_equal true, app.config.assets.debug
121 | assert_equal true, app.config.assets.compile
122 |
123 | app.initialize!
124 |
125 | # Resolves against environment only
126 | assert_equal [ :environment ], app.config.assets.resolve_with
127 | end
128 |
129 | def test_copies_paths
130 | app.configure do
131 | config.assets.paths << "javascripts"
132 | config.assets.paths << "stylesheets"
133 | end
134 | app.initialize!
135 |
136 | assert env = app.assets
137 | assert_includes(env.paths, "#{ROOT}/javascripts")
138 | assert_includes(env.paths, "#{ROOT}/stylesheets")
139 | assert_includes(env.paths, "#{ROOT}/app/assets/config")
140 | end
141 |
142 | def test_compressors
143 | app.configure do
144 | config.assets.js_compressor = :uglifier
145 | config.assets.css_compressor = :sass
146 | end
147 | app.initialize!
148 |
149 | assert env = app.assets
150 | assert_equal Sprockets::UglifierCompressor.name, env.js_compressor.name
151 |
152 | silence_warnings do
153 | require 'sprockets/sass_compressor'
154 | end
155 | assert_equal Sprockets::SassCompressor.name, env.css_compressor.name
156 | end
157 |
158 | def test_custom_compressors
159 | compressor = Class.new do
160 | def self.call(input)
161 | { data: input[:data] }
162 | end
163 | end
164 |
165 | app.configure do
166 | config.assets.configure do |env|
167 | env.register_compressor "application/javascript", :test_js, compressor
168 | env.register_compressor "text/css", :test_css, compressor
169 | end
170 | config.assets.js_compressor = :test_js
171 | config.assets.css_compressor = :test_css
172 | end
173 | app.initialize!
174 |
175 | assert env = app.assets
176 | assert_equal compressor, env.js_compressor
177 | assert_equal compressor, env.css_compressor
178 | end
179 |
180 | def test_default_gzip_config
181 | app.initialize!
182 |
183 | assert env = app.assets
184 | assert_equal true, env.gzip?
185 | end
186 |
187 | def test_gzip_config
188 | app.configure do
189 | config.assets.gzip = false
190 | end
191 | app.initialize!
192 |
193 | assert env = app.assets
194 | assert_equal false, env.gzip?
195 | end
196 |
197 | def test_default_check_precompiled_assets
198 | assert app.config.assets.check_precompiled_asset
199 | app.initialize!
200 | @view = action_view
201 | assert @view.check_precompiled_asset
202 | end
203 |
204 | def test_configure_check_precompiled_assets
205 | app.configure do
206 | config.assets.check_precompiled_asset = false
207 | end
208 | app.initialize!
209 | @view = action_view
210 | refute @view.check_precompiled_asset
211 | end
212 |
213 | def test_version
214 | app.configure do
215 | config.assets.version = 'v2'
216 | end
217 | app.initialize!
218 |
219 | assert env = app.assets
220 | assert_equal "v2", env.version
221 | end
222 |
223 | def test_configure
224 | app.configure do
225 | config.assets.configure do |env|
226 | env.append_path "javascripts"
227 | end
228 | config.assets.configure do |env|
229 | env.append_path "stylesheets"
230 | end
231 | end
232 | app.initialize!
233 |
234 | assert env = app.assets
235 |
236 | assert_includes(env.paths, "#{ROOT}/javascripts")
237 | assert_includes(env.paths, "#{ROOT}/stylesheets")
238 | assert_includes(env.paths, "#{ROOT}/app/assets/config")
239 | end
240 |
241 | def test_environment_is_frozen_if_caching_classes
242 | app.configure do
243 | config.cache_classes = true
244 | end
245 | app.initialize!
246 |
247 | assert env = app.assets
248 | assert_kind_of Sprockets::CachedEnvironment, env
249 | end
250 |
251 | def test_action_view_helper
252 | app.configure do
253 | config.assets.paths << FIXTURES_PATH
254 | config.assets.precompile += ["foo.js"]
255 | end
256 | app.initialize!
257 |
258 | assert app.assets.paths.include?(FIXTURES_PATH)
259 |
260 | assert_equal false, ActionView::Base.debug_assets
261 | assert_equal true, ActionView::Base.digest_assets
262 | assert_equal "/assets", ActionView::Base.assets_prefix
263 | assert_equal app.assets, ActionView::Base.assets_environment
264 | assert_equal app.assets_manifest, ActionView::Base.assets_manifest
265 | assert_kind_of Sprockets::Environment, ActionView::Base.assets_environment
266 |
267 | @view = action_view
268 | assert_equal "/javascripts/xmlhr.js", @view.javascript_path("xmlhr")
269 | assert_equal "/assets/foo-4ef5541f349f7ed5a0d6b71f2fa4c82745ca106ae02f212aea5129726ac6f6ab.js", @view.javascript_path("foo")
270 |
271 | env = @view.assets_environment
272 | assert_kind_of Sprockets::CachedEnvironment, env
273 | assert @view.assets_environment.equal?(env), "view didn't return the same cached instance"
274 | end
275 |
276 | def test_action_view_helper_when_no_compile
277 | app.configure do
278 | config.assets.compile = false
279 | end
280 |
281 | assert_equal false, app.config.assets.compile
282 |
283 | app.initialize!
284 |
285 | refute ActionView::Base.assets_environment
286 | assert_equal app.assets_manifest, ActionView::Base.assets_manifest
287 |
288 | @view = action_view
289 | refute @view.assets_environment
290 | assert_equal app.assets_manifest, @view.assets_manifest
291 | end
292 |
293 | def test_sprockets_context_helper
294 | app.initialize!
295 |
296 | assert env = app.assets
297 | assert_equal "/assets", env.context_class.assets_prefix
298 | assert_equal true, env.context_class.digest_assets
299 | assert_nil env.context_class.config.asset_host
300 | end
301 |
302 | def test_manifest_path
303 | app.configure do
304 | config.assets.manifest = Rails.root.join('config','foo','bar.json')
305 | end
306 | app.initialize!
307 |
308 | assert manifest = app.assets_manifest
309 | assert_match %r{config/foo/bar\.json$}, manifest.path
310 | assert_match %r{public/assets$}, manifest.dir
311 | end
312 |
313 | def test_manifest_path_respects_rails_public_path
314 | app.configure do
315 | config.paths['public'] = 'test_public'
316 | end
317 | app.initialize!
318 |
319 | assert manifest = app.assets_manifest
320 | assert_match %r{test_public/assets/\.sprockets-manifest-.*\.json$}, manifest.path
321 | assert_match %r{test_public/assets$}, manifest.dir
322 | end
323 |
324 | def test_load_tasks
325 | app.initialize!
326 | app.load_tasks
327 |
328 | assert Rake.application['assets:environment']
329 | assert Rake.application['assets:precompile']
330 | assert Rake.application['assets:clean']
331 | assert Rake.application['assets:clobber']
332 | end
333 |
334 | def test_task_precompile
335 | app.configure do
336 | config.assets.paths << FIXTURES_PATH
337 | config.assets.precompile += ["foo.js", "url.css"]
338 | end
339 | app.initialize!
340 | app.load_tasks
341 |
342 | path = "#{app.assets_manifest.dir}/foo-#{Rails.application.assets['foo.js'].etag}.js"
343 |
344 | silence_stderr do
345 | Rake.application['assets:clobber'].execute
346 | end
347 | refute File.exist?(path)
348 |
349 | silence_stderr do
350 | Rake.application['assets:precompile'].execute
351 | end
352 | assert File.exist?(path)
353 | url_css_path = File.join(app.assets_manifest.dir, Rails.application.assets['url.css'].digest_path)
354 | assert_match(%r{/assets/logo-#{Rails.application.assets['logo.png'].etag}.png}, File.read(url_css_path))
355 |
356 | silence_stderr do
357 | Rake.application['assets:clobber'].execute
358 | end
359 | refute File.exist?(path)
360 | end
361 |
362 | def test_task_precompile_compile_false
363 | app.configure do
364 | config.assets.compile = false
365 | config.assets.paths << FIXTURES_PATH
366 | config.assets.precompile += ["foo.js"]
367 | end
368 | app.initialize!
369 | app.load_tasks
370 |
371 | path = "#{app.assets_manifest.dir}/foo-4ef5541f349f7ed5a0d6b71f2fa4c82745ca106ae02f212aea5129726ac6f6ab.js"
372 |
373 | silence_stderr do
374 | Rake.application['assets:clobber'].execute
375 | end
376 | refute File.exist?(path)
377 |
378 | silence_stderr do
379 | Rake.application['assets:precompile'].execute
380 | end
381 | assert File.exist?(path)
382 |
383 | silence_stderr do
384 | Rake.application['assets:clobber'].execute
385 | end
386 | refute File.exist?(path)
387 | end
388 |
389 | def test_direct_build_environment_call
390 | app.configure do
391 | config.assets.paths << "javascripts"
392 | config.assets.paths << "stylesheets"
393 | end
394 | app.initialize!
395 |
396 | assert env = Sprockets::Railtie.build_environment(app)
397 | assert_kind_of Sprockets::Environment, env
398 |
399 | assert_equal ROOT, env.root
400 | assert_includes(env.paths, "#{ROOT}/javascripts")
401 | assert_includes(env.paths, "#{ROOT}/stylesheets")
402 | assert_includes(env.paths, "#{ROOT}/app/assets/config")
403 | end
404 |
405 | def test_quiet_assets_defaults_to_off
406 | app.initialize!
407 | app.load_tasks
408 |
409 | assert_equal false, app.config.assets.quiet
410 | refute app.config.middleware.include?(Sprockets::Rails::QuietAssets)
411 | end
412 |
413 | def test_quiet_assets_inserts_middleware
414 | app.configure do
415 | config.assets.quiet = true
416 | end
417 | app.initialize!
418 | app.load_tasks
419 | middleware = app.config.middleware
420 |
421 | assert_equal true, app.config.assets.quiet
422 | assert middleware.include?(Sprockets::Rails::QuietAssets)
423 | assert middleware.each_cons(2).include?([Sprockets::Rails::QuietAssets, Rails::Rack::Logger])
424 | end
425 |
426 | def test_resolve_assets_in_css_urls_defaults_to_true
427 | app.initialize!
428 |
429 | assert_equal true, app.config.assets.resolve_assets_in_css_urls
430 | assert_includes Sprockets.postprocessors['text/css'], Sprockets::Rails::AssetUrlProcessor
431 | end
432 |
433 | def test_resolve_assets_in_css_urls_when_false_avoids_registering_postprocessor
434 | app.configure do
435 | config.assets.resolve_assets_in_css_urls = false
436 | end
437 | app.initialize!
438 |
439 | assert_equal false, app.config.assets.resolve_assets_in_css_urls
440 | refute_includes Sprockets.postprocessors['text/css'], Sprockets::Rails::AssetUrlProcessor
441 | end
442 |
443 | private
444 | def action_view
445 | ActionView::Base.new(ActionView::LookupContext.new([]), {}, nil)
446 | end
447 | end
448 |
--------------------------------------------------------------------------------
/test/test_sourcemapping_url_processor.rb:
--------------------------------------------------------------------------------
1 | require 'minitest/autorun'
2 | require 'sprockets/railtie'
3 |
4 | Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
5 | class TestSourceMappingUrlProcessor < Minitest::Test
6 | def setup
7 | @env = Sprockets::Environment.new
8 | end
9 |
10 | def test_successful
11 | @env.context_class.class_eval do
12 | def resolve(path, **kargs)
13 | "/assets/mapped.js.map"
14 | end
15 |
16 | def asset_path(path, options = {})
17 | "/assets/mapped-HEXGOESHERE.js.map"
18 | end
19 | end
20 |
21 | input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mapped.js.map", name: 'mapped', filename: 'mapped.js', metadata: {} }
22 | output = Sprockets::Rails::SourcemappingUrlProcessor.call(input)
23 | assert_equal({ data: "var mapped;\n//# sourceMappingURL=/assets/mapped-HEXGOESHERE.js.map\n//!\n" }, output)
24 | end
25 |
26 | def test_resolving_erroneously_without_map_extension
27 | @env.context_class.class_eval do
28 | def resolve(path, **kargs)
29 | "/assets/mapped.js"
30 | end
31 | end
32 |
33 | input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mapped.js.map", name: 'mapped', filename: 'mapped.js', metadata: {} }
34 | output = Sprockets::Rails::SourcemappingUrlProcessor.call(input)
35 | assert_equal({ data: "var mapped;\n" }, output)
36 | end
37 |
38 | def test_missing
39 | @env.context_class.class_eval do
40 | def resolve(path, **kargs)
41 | raise Sprockets::FileNotFound
42 | end
43 | end
44 |
45 | input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mappedNOT.js.map", name: 'mapped', filename: 'mapped.js', metadata: {} }
46 | output = Sprockets::Rails::SourcemappingUrlProcessor.call(input)
47 | assert_equal({ data: "var mapped;\n" }, output)
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/test/test_task.rb:
--------------------------------------------------------------------------------
1 | require 'minitest/autorun'
2 | require 'tmpdir'
3 |
4 | require 'sprockets'
5 | require 'sprockets/rails/task'
6 |
7 | Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
8 |
9 | class TestTask < Minitest::Test
10 | FIXTURES_PATH = File.expand_path("../fixtures", __FILE__)
11 |
12 | def setup
13 | @rake = Rake::Application.new
14 | Rake.application = @rake
15 |
16 | @assets = Sprockets::Environment.new
17 | @assets.append_path FIXTURES_PATH
18 |
19 | @dir = File.join(Dir::tmpdir, 'rails', 'task')
20 |
21 | @manifest_file = File.join(Dir::tmpdir, 'rails', 'manifest', 'custom-manifest.json')
22 | FileUtils.mkdir_p File.dirname(@manifest_file)
23 | @manifest = Sprockets::Manifest.new(@assets, @dir, @manifest_file)
24 |
25 | Sprockets::Rails::Task.new do |t|
26 | t.environment = @assets
27 | t.manifest = @manifest
28 | t.assets = ['foo.js', 'foo-modified.js']
29 | t.log_level = :fatal
30 | end
31 |
32 | @environment_ran = false
33 | # Stub Rails environment task
34 | @rake.define_task Rake::Task, :environment do
35 | @environment_ran = true
36 | end
37 | end
38 |
39 | def teardown
40 | Rake.application = nil
41 |
42 | FileUtils.rm_rf(@dir)
43 | assert Dir["#{@dir}/*"].empty?
44 |
45 | manifest_dir = File.dirname(@manifest_file)
46 | FileUtils.rm_rf(manifest_dir)
47 | assert Dir["#{manifest_dir}/*"].empty?
48 | end
49 |
50 | def test_precompile
51 | assert !@environment_ran
52 |
53 | digest_path = @assets['foo.js'].digest_path
54 | assert !File.exist?("#{@dir}/#{digest_path}")
55 |
56 | @rake['assets:precompile'].invoke
57 |
58 | assert @environment_ran
59 | assert File.exist?(@manifest_file)
60 | assert File.exist?("#{@dir}/#{digest_path}")
61 | end
62 |
63 | def test_precompile_without_manifest
64 | Sprockets::Rails::Task.new do |t|
65 | t.environment = @assets
66 | t.manifest = Sprockets::Manifest.new(@assets, @dir, nil)
67 | t.assets = ['foo.js', 'foo-modified.js']
68 | t.log_level = :fatal
69 | end
70 |
71 | assert !@environment_ran
72 |
73 | digest_path = @assets['foo.js'].digest_path
74 | assert !File.exist?("#{@dir}/#{digest_path}")
75 |
76 | @rake['assets:precompile'].invoke
77 |
78 | assert @environment_ran
79 | assert Dir["#{@dir}/.sprockets-manifest-*.json"].first
80 | assert File.exist?("#{@dir}/#{digest_path}")
81 | end
82 |
83 | def test_clobber
84 | assert !@environment_ran
85 | digest_path = @assets['foo.js'].digest_path
86 |
87 | @rake['assets:precompile'].invoke
88 | assert File.exist?("#{@dir}/#{digest_path}")
89 |
90 | assert @environment_ran
91 |
92 | @rake['assets:clobber'].invoke
93 | assert !File.exist?("#{@dir}/#{digest_path}")
94 | end
95 |
96 | def test_clean
97 | assert !@environment_ran
98 | digest_path = @assets['foo.js'].digest_path
99 |
100 | @rake['assets:precompile'].invoke
101 | assert File.exist?("#{@dir}/#{digest_path}")
102 |
103 | assert @environment_ran
104 |
105 | @rake['assets:clean'].invoke
106 | assert File.exist?("#{@dir}/#{digest_path}")
107 | end
108 |
109 | def test_clean_with_keep_specified
110 | assert !@environment_ran
111 | path = Pathname.new(@assets['foo.js'].filename)
112 | new_path = path.join("../foo-modified.js")
113 |
114 | FileUtils.cp(path, new_path)
115 |
116 | assert File.exist?(new_path)
117 | digest_path = @assets['foo-modified.js'].digest_path
118 |
119 | @rake['assets:precompile'].invoke
120 | assert File.exist?("#{@dir}/#{digest_path}")
121 | assert @environment_ran
122 |
123 | # clean environment
124 | setup
125 |
126 | # modify file
127 | File.open(new_path, "a") {|f| f.write("var Bar;") }
128 | @rake['assets:precompile'].invoke
129 | old_digest_path = digest_path
130 | digest_path = @assets['foo-modified.js'].digest_path
131 |
132 | refute_equal old_digest_path, digest_path
133 | assert File.exist?("#{@dir}/#{old_digest_path}")
134 | assert File.exist?("#{@dir}/#{digest_path}")
135 |
136 | @rake['assets:clean'].invoke(0)
137 | assert File.exist?("#{@dir}/#{digest_path}")
138 | # refute File.exist?("#{@dir}/#{old_digest_path}")
139 | ensure
140 | FileUtils.rm(new_path) if new_path
141 | end
142 | end
143 |
--------------------------------------------------------------------------------