Skip to content

Commit

Permalink
backport
Browse files Browse the repository at this point in the history
  • Loading branch information
derekrockwell committed Jul 14, 2015
1 parent 34ae184 commit e13aa82
Show file tree
Hide file tree
Showing 7 changed files with 302 additions and 297 deletions.
41 changes: 12 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Only removes old assets (keeps the most recent 3 copies) from `public/assets`. U

**`rake assets:clobber`**

Nuke `public/assets`.
Nuke `public/assets` and clear the Sprockets file system cache.

#### Customize

Expand All @@ -37,7 +37,7 @@ You can also redefine the task with the built in task generator.

``` ruby
require 'sprockets/rails/task'
Sprockets::Rails::Task.new(Rails.application) do |t|
Sprockets::Rails::Task.new do |t|
t.environment = lambda { Rails.application.assets }
t.assets = %w( application.js application.css )
t.keep = 5
Expand All @@ -46,7 +46,7 @@ end

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.

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).
Also see [Sprockest::Rails::Task](https://github.com/josh/sprockets-rails/blob/master/lib/sprockets/rails/task.rb) and [Rake::SprocketsTask](https://github.com/sstephenson/sprockets/blob/master/lib/rake/sprocketstask.rb).


### Initializer options
Expand All @@ -57,8 +57,7 @@ Add additional assets to compile on deploy. Defaults to `application.js`, `appli

**`config.assets.paths`**

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.

Add additional load paths to this Array. Rails includes `app/assets` and `vendor/assets` for you already. Plugins might want to add their custom paths to to this.

**`config.assets.version`**

Expand All @@ -74,29 +73,25 @@ config.assets.version = 'v2'

Defaults to `/assets`. Changes the directory to compile assets to.

**`config.assets.manifest`**

Defines the full path to be used for the asset precompiler's manifest file. Defaults to a randomly-generated filename in the `config.assets.prefix` directory within the public folder.

**`config.assets.digest`**

When enabled, fingerprints will be added to asset filenames.
Link to undigest asset filenames. This option will eventually go away. Unless when `compile` is disabled.

**`config.assets.debug`**

Enable expanded asset debugging mode. Individual files will be served to make referencing filenames in the web console easier. This feature will eventually be deprecated and replaced by Source Maps in Sprockets 3.x.

**`config.assets.compile`**

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.
Enables Sprockest compile environment. If disabled, `Rails.application.assets` will be unavailable to any ActionView helpers. View helpers will depend on assets being precompiled to `public/assets` in order to link to them. You can still access the environment by directly calling `Rails.application.assets`.

**`config.assets.configure`**

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.

``` ruby
config.assets.configure do |env|
env.js_compressor = :uglifier # or :closure, :yui
env.js_compressor = :uglify # or :closure, :yui
env.css_compressor = :sass # or :yui

require 'my_processor'
Expand All @@ -123,22 +118,10 @@ The following plugins provide some extras for the Sprockets Asset Pipeline.

* Only compiles digest filenames. Static non-digest assets should simply live in public/.
* 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.
* 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.
* 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 = :uglify` or `config.assets.css_compressor = :sass` for the standard compressors.
* 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.
* `config.assets.manifest` (if used) must now include the manifest filename, e.g. `Rails.root.join('config/manifest.json')`. It cannot be a directory.
* 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 and clears your filesystem cache. The clean task allows for rolling deploys that may still be linking to an old asset while the new assets are being built.

## Experimental

### [SRI](http://www.w3.org/TR/SRI/) support

Sprockets 3.x adds experimental support for subresource integrity checks. The spec is still evolving and the API may change in backwards incompatible ways.

``` ruby
javascript_include_tag :application, integrity: true
# => "<script src="/assets/application.js" integrity="sha-256-TvVUHzSfftWg1rcfL6TIJ0XKEGrgLyEq6lEpcmrG9qs="></script>"
```


## Contributing

Expand All @@ -151,22 +134,22 @@ $ bundle install
$ bundle exec rake test
```

[![Build Status](https://travis-ci.org/rails/sprockets-rails.svg?branch=master)](https://travis-ci.org/rails/sprockets-rails)
[![Build Status](https://secure.travis-ci.org/rails/sprockets-rails.png)](http://travis-ci.org/rails/sprockets-rails)


## Releases

sprockets-rails 3.x will primarily target sprockets 3.x. And future versions will target the corresponding sprockets release line.
sprockets-rails 2.x will primarily target sprockets 2.x. And future versions will target the corresponding sprockets release line.

The minor and patch version will be updated according to [semver](http://semver.org/).

* Any new APIs or config options that don't break compatibility will be in a minor release
* Any time the sprockets dependency is bumped, there will be a new minor release
* Any time the sprockets depedency is bumped, there will be a new minor release
* Simple bug fixes will be patch releases


## License

Copyright &copy; 2014 Joshua Peek.
Copyright &copy; 2012 Joshua Peek.

Released under the MIT license. See `LICENSE` for details.
1 change: 0 additions & 1 deletion lib/sprockets/rails.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
require 'sprockets/rails/version'
if defined? Rails::Railtie
require 'sprockets/railtie'
end
172 changes: 33 additions & 139 deletions lib/sprockets/rails/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,57 +5,38 @@
module Sprockets
module Rails
module Helper
class AssetNotPrecompiled < StandardError
def initialize(source)
msg = "Asset was not declared to be precompiled in production.\n" +
"Add `Rails.application.config.assets.precompile += " +
"%w( #{source} )` to `config/initializers/assets.rb` and " +
"restart your server"
super(msg)
end
if defined? ActionView::Helpers::AssetUrlHelper
include ActionView::Helpers::AssetUrlHelper
else
require 'sprockets/rails/legacy_asset_tag_helper'
require 'sprockets/rails/legacy_asset_url_helper'
include LegacyAssetTagHelper
include LegacyAssetUrlHelper
end

include ActionView::Helpers::AssetUrlHelper
include ActionView::Helpers::AssetTagHelper

VIEW_ACCESSORS = [:assets_environment, :assets_manifest,
:assets_precompile,
:assets_prefix, :digest_assets, :debug_assets]

def self.included(klass)
klass.class_attribute(*VIEW_ACCESSORS)

klass.class_eval do
remove_method :assets_environment
def assets_environment
if instance_variable_defined?(:@assets_environment)
@assets_environment = @assets_environment.cached
elsif env = self.class.assets_environment
@assets_environment = env.cached
else
nil
end
if klass < Sprockets::Context
klass.class_eval do
alias_method :assets_environment, :environment
def assets_manifest; end
class_attribute :config, :assets_prefix, :digest_assets
end
else
klass.class_attribute(*VIEW_ACCESSORS)
end
end

def self.extended(obj)
obj.class_eval do
attr_accessor(*VIEW_ACCESSORS)

remove_method :assets_environment
def assets_environment
if env = @assets_environment
@assets_environment = env.cached
else
nil
end
end
end
end

def compute_asset_path(path, options = {})
if digest_path = asset_digest_path(path, options)
if digest_path = asset_digest_path(path)
path = digest_path if digest_assets
path += "?body=1" if options[:debug]
File.join(assets_prefix || "/", path)
Expand All @@ -64,58 +45,38 @@ def compute_asset_path(path, options = {})
end
end

# Expand asset path to digested form.
# Get digest for asset path.
#
# path - String path
# options - Hash options
#
# Returns String path or nil if no asset was found.
def asset_digest_path(path, options = {})
if manifest = assets_manifest
if digest_path = manifest.assets[path]
return digest_path
end
end
# Returns String Hex digest or nil if digests are disabled.
def asset_digest(path, options = {})
return unless digest_assets

if environment = assets_environment
if asset = environment[path]
unless options[:debug]
if !precompiled_assets.include?(asset)
raise AssetNotPrecompiled.new(asset.logical_path)
end
end
return asset.digest_path
end
if digest_path = asset_digest_path(path, options)
digest_path[/-(.+)\./, 1]
end
end

# Experimental: Get integrity for asset path.
# Expand asset path to digested form.
#
# path - String path
# options - Hash options
#
# Returns String integrity attribute or nil if no asset was found.
def asset_integrity(path, options = {})
path = path.to_s
if extname = compute_asset_extname(path, options)
path = "#{path}#{extname}"
end

# Returns String path or nil if no asset was found.
def asset_digest_path(path, options = {})
if manifest = assets_manifest
if digest_path = manifest.assets[path]
if metadata = manifest.files[digest_path]
return metadata["integrity"]
end
return digest_path
end
end

if environment = assets_environment
if asset = environment[path]
return asset.integrity
return asset.digest_path
end
end

nil
end

# Override javascript tag helper to provide debugging support.
Expand All @@ -124,16 +85,7 @@ def asset_integrity(path, options = {})
def javascript_include_tag(*sources)
options = sources.extract_options!.stringify_keys

unless request_ssl?
options.delete("integrity")
end

case options["integrity"]
when true, false, nil
compute_integrity = options.delete("integrity")
end

if options["debug"] != false && request_debug_assets?
if request_debug_assets?
sources.map { |source|
if asset = lookup_asset_for_path(source, :type => :javascript)
asset.to_a.map do |a|
Expand All @@ -144,11 +96,8 @@ def javascript_include_tag(*sources)
end
}.flatten.uniq.join("\n").html_safe
else
sources.map { |source|
super(source, compute_integrity ?
options.merge("integrity" => asset_integrity(source, :type => :javascript)) :
options)
}.join("\n").html_safe
sources.push(options)
super(*sources)
end
end

Expand All @@ -158,16 +107,7 @@ def javascript_include_tag(*sources)
def stylesheet_link_tag(*sources)
options = sources.extract_options!.stringify_keys

unless request_ssl?
options.delete("integrity")
end

case options["integrity"]
when true, false, nil
compute_integrity = options.delete("integrity")
end

if options["debug"] != false && request_debug_assets?
if request_debug_assets?
sources.map { |source|
if asset = lookup_asset_for_path(source, :type => :stylesheet)
asset.to_a.map do |a|
Expand All @@ -178,25 +118,16 @@ def stylesheet_link_tag(*sources)
end
}.flatten.uniq.join("\n").html_safe
else
sources.map { |source|
super(source, compute_integrity ?
options.merge("integrity" => asset_integrity(source, :type => :stylesheet)) :
options)
}.join("\n").html_safe
sources.push(options)
super(*sources)
end
end

protected
def request_ssl?
respond_to?(:request) && self.request && self.request.ssl?
end

# Enable split asset debugging. Eventually will be deprecated
# and replaced by source maps in Sprockets 3.x.
def request_debug_assets?
debug_assets || (defined?(controller) && controller && params[:debug_assets])
rescue
return false
end

# Internal method to support multifile debugging. Will
Expand All @@ -207,44 +138,7 @@ def lookup_asset_for_path(path, options = {})
if extname = compute_asset_extname(path, options)
path = "#{path}#{extname}"
end

if asset = env[path]
if !precompiled_assets.include?(asset)
raise AssetNotPrecompiled.new(asset.logical_path)
end
end

asset
end

# Internal: Generate a Set of all precompiled assets.
def precompiled_assets
@precompiled_assets ||= begin
assets = Set.new

paths, filters = (assets_precompile || []).flatten.partition { |arg| Sprockets::Manifest.simple_logical_path?(arg) }
filters = filters.map { |arg| Sprockets::Manifest.compile_match_filter(arg) }

env = assets_environment.cached

paths.each do |path|
env.find_all_linked_assets(path) do |asset|
assets << asset
end
end

if filters.any?
env.logical_paths do |logical_path, filename|
if filters.any? { |f| f.call(logical_path, filename) }
env.find_all_linked_assets(filename) do |asset|
assets << asset
end
end
end
end

assets
end
env[path]
end
end
end
Expand Down
Loading

0 comments on commit e13aa82

Please sign in to comment.