Class: Sprockets::Manifest
- Inherits:
-
Object
- Object
- Sprockets::Manifest
- Defined in:
- lib/sprockets/manifest.rb
Overview
The Manifest logs the contents of assets compiled to a single directory. It records basic attributes about the asset for fast lookup without having to compile. A pointer from each logical path indicates with fingerprinted asset is the current one.
The JSON is part of the public API and should be considered stable. This should make it easy to read from other programming languages and processes that don’t have sprockets loaded. See ‘#assets` and `#files` for more infomation about the structure.
Instance Attribute Summary collapse
-
#dir ⇒ Object
readonly
Returns the value of attribute dir.
-
#environment ⇒ Object
readonly
Returns the value of attribute environment.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Instance Method Summary collapse
-
#assets ⇒ Object
Returns internal assets mapping.
-
#clean(keep = 2) ⇒ Object
Cleanup old assets in the compile directory.
-
#clobber ⇒ Object
Wipe directive.
-
#compile(*args) ⇒ Object
Compile and write asset to directory.
-
#files ⇒ Object
Returns internal file directory listing.
-
#initialize(*args) ⇒ Manifest
constructor
Create new Manifest associated with an ‘environment`.
-
#remove(filename) ⇒ Object
Removes file from directory and from manifest.
Constructor Details
#initialize(*args) ⇒ Manifest
Create new Manifest associated with an ‘environment`. `path` is a full path to the manifest json file. The file may or may not already exist. The dirname of the `path` will be used to write compiled assets to. Otherwise, if the path is a directory, the filename will default a random “manifest-123.json” file in that directory.
Manifest.new(environment, "./public/assets/manifest.json")
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/sprockets/manifest.rb', line 27 def initialize(*args) if args.first.is_a?(Base) || args.first.nil? @environment = args.shift end @dir, @path = args[0], args[1] # Expand paths @dir = File.(@dir) if @dir @path = File.(@path) if @path # If path is given as the second arg if @dir && File.extname(@dir) != "" @dir, @path = nil, @dir end # Default dir to the directory of the path @dir ||= File.dirname(@path) if @path # If directory is given w/o path, pick a random manifest.json location if @dir && @path.nil? # Find the first manifest.json in the directory paths = Dir[File.join(@dir, "manifest*.json")] if paths.any? @path = paths.first else @path = File.join(@dir, "manifest-#{SecureRandom.hex(16)}.json") end end unless @dir && @path raise ArgumentError, "manifest requires output path" end data = nil begin if File.exist?(@path) data = json_decode(File.read(@path)) end rescue MultiJson::DecodeError => e logger.error "#{@path} is invalid: #{e.class} #{e.}" end @data = data.is_a?(Hash) ? data : {} end |
Instance Attribute Details
#dir ⇒ Object (readonly)
Returns the value of attribute dir.
16 17 18 |
# File 'lib/sprockets/manifest.rb', line 16 def dir @dir end |
#environment ⇒ Object (readonly)
Returns the value of attribute environment.
16 17 18 |
# File 'lib/sprockets/manifest.rb', line 16 def environment @environment end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
16 17 18 |
# File 'lib/sprockets/manifest.rb', line 16 def path @path end |
Instance Method Details
#assets ⇒ Object
Returns internal assets mapping. Keys are logical paths which map to the latest fingerprinted filename.
Logical path (String): Fingerprint path (String)
{ "application.js" => "application-2e8e9a7c6b0aafa0c9bdeec90ea30213.js",
"jquery.js" => "jquery-ae0908555a245f8266f77df5a8edca2e.js" }
82 83 84 |
# File 'lib/sprockets/manifest.rb', line 82 def assets @data['assets'] ||= {} end |
#clean(keep = 2) ⇒ Object
Cleanup old assets in the compile directory. By default it will keep the latest version plus 2 backups.
171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/sprockets/manifest.rb', line 171 def clean(keep = 2) self.assets.keys.each do |logical_path| # Get assets sorted by ctime, newest first assets = backups_for(logical_path) # Keep the last N backups assets = assets[keep..-1] || [] # Remove old assets assets.each { |path, _| remove(path) } end end |
#clobber ⇒ Object
Wipe directive
185 186 187 188 189 |
# File 'lib/sprockets/manifest.rb', line 185 def clobber FileUtils.rm_r(@dir) if File.exist?(@dir) logger.info "Removed #{@dir}" nil end |
#compile(*args) ⇒ Object
Compile and write asset to directory. The asset is written to a fingerprinted filename like ‘application-2e8e9a7c6b0aafa0c9bdeec90ea30213.js`. An entry is also inserted into the manifest file.
compile("application.js")
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/sprockets/manifest.rb', line 110 def compile(*args) unless environment raise Error, "manifest requires environment for compilation" end paths = environment.each_logical_path(*args).to_a + args.flatten.select { |fn| Pathname.new(fn).absolute? if fn.is_a?(String)} paths.each do |path| if asset = find_asset(path) files[asset.digest_path] = { 'logical_path' => asset.logical_path, 'mtime' => asset.mtime.iso8601, 'size' => asset.bytesize, 'digest' => asset.digest } assets[asset.logical_path] = asset.digest_path target = File.join(dir, asset.digest_path) if File.exist?(target) logger.debug "Skipping #{target}, already exists" else logger.info "Writing #{target}" asset.write_to target asset.write_to "#{target}.gz" if asset.is_a?(BundledAsset) end save asset end end end |
#files ⇒ Object
Returns internal file directory listing. Keys are filenames which map to an attributes array.
Fingerprint path (String):
logical_path: Logical path (String)
mtime: ISO8601 mtime (String)
digest: Base64 hex digest (String)
{ "application-2e8e9a7c6b0aafa0c9bdeec90ea30213.js" =>
{ 'logical_path' => "application.js",
'mtime' => "2011-12-13T21:47:08-06:00",
'digest' => "2e8e9a7c6b0aafa0c9bdeec90ea30213" } }
99 100 101 |
# File 'lib/sprockets/manifest.rb', line 99 def files @data['files'] ||= {} end |
#remove(filename) ⇒ Object
Removes file from directory and from manifest. ‘filename` must be the name with any directory path.
manifest.remove("application-2e8e9a7c6b0aafa0c9bdeec90ea30213.js")
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/sprockets/manifest.rb', line 149 def remove(filename) path = File.join(dir, filename) gzip = "#{path}.gz" logical_path = files[filename]['logical_path'] if assets[logical_path] == filename assets.delete(logical_path) end files.delete(filename) FileUtils.rm(path) if File.exist?(path) FileUtils.rm(gzip) if File.exist?(gzip) save logger.info "Removed #{filename}" nil end |