1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
# frozen_string_literal: true
require 'fileutils'
require 'sprockets/digest_utils'
module Sprockets
class Asset
attr_reader :logical_path
# Private: Initialize Asset wrapper from attributes Hash.
#
# Asset wrappers should not be initialized directly, only
# Environment#find_asset should vend them.
#
# attributes - Hash of ivars
#
# Returns Asset.
def initialize(attributes = {})
@attributes = attributes
@content_type = attributes[:content_type]
@filename = attributes[:filename]
@id = attributes[:id]
@load_path = attributes[:load_path]
@logical_path = attributes[:logical_path]
@metadata = attributes[:metadata]
@name = attributes[:name]
@source = attributes[:source]
@uri = attributes[:uri]
end
# Internal: Return all internal instance variables as a hash.
#
# Returns a Hash.
def to_hash
@attributes
end
# Public: Metadata accumulated from pipeline process.
#
# The API status of the keys is dependent on the pipeline processors
# itself. So some values maybe considered public and others internal.
# See the pipeline processor documentation itself.
#
# Returns Hash.
attr_reader :metadata
# Public: Returns String path of asset.
attr_reader :filename
# Internal: Unique asset object ID.
#
# Returns a String.
attr_reader :id
# Public: Internal URI to lookup asset by.
#
# NOT a publicly accessible URL.
#
# Returns URI.
attr_reader :uri
# Public: Return logical path with digest spliced in.
#
# "foo/bar-37b51d194a7513e45b56f6524f2d51f2.js"
#
# Returns String.
def digest_path
if DigestUtils.already_digested?(@name)
logical_path
else
logical_path.sub(/\.(\w+)$/) { |ext| "-#{etag}#{ext}" }
end
end
# Public: Return load path + logical path with digest spliced in.
#
# Returns String.
def full_digest_path
File.join(@load_path, digest_path)
end
# Public: Returns String MIME type of asset. Returns nil if type is unknown.
attr_reader :content_type
# Public: Get all externally linked asset filenames from asset.
#
# All linked assets should be compiled anytime this asset is.
#
# Returns Set of String asset URIs.
def links
metadata[:links] || Set.new
end
# Public: Return `String` of concatenated source.
#
# Returns String.
def source
if @source
@source
else
# File is read everytime to avoid memory bloat of large binary files
File.binread(filename)
end
end
# Public: Alias for #source.
#
# Returns String.
def to_s
source
end
# Public: Get charset of source.
#
# Returns a String charset name or nil if binary.
def charset
metadata[:charset]
end
# Public: Returns Integer length of source.
def length
metadata[:length]
end
alias_method :bytesize, :length
# Public: Returns String byte digest of source.
def digest
metadata[:digest]
end
# Private: Return the version of the environment where the asset was generated.
def environment_version
metadata[:environment_version]
end
# Public: Returns String hexdigest of source.
def hexdigest
DigestUtils.pack_hexdigest(digest)
end
# Public: ETag String of Asset.
def etag
version = environment_version
if version && version != ""
DigestUtils.hexdigest(version + digest)
else
DigestUtils.pack_hexdigest(digest)
end
end
# Public: Returns String base64 digest of source.
def base64digest
DigestUtils.pack_base64digest(digest)
end
# Public: A "named information" URL for subresource integrity.
def integrity
DigestUtils.integrity_uri(digest)
end
# Public: Add enumerator to allow `Asset` instances to be used as Rack
# compatible body objects.
#
# block
# part - String body chunk
#
# Returns nothing.
def each
yield to_s
end
# Deprecated: Save asset to disk.
#
# filename - String target
#
# Returns nothing.
def write_to(filename)
FileUtils.mkdir_p File.dirname(filename)
PathUtils.atomic_write(filename) do |f|
f.write source
end
nil
end
# Public: Pretty inspect
#
# Returns String.
def inspect
"#<#{self.class}:#{object_id.to_s(16)} #{uri.inspect}>"
end
# Public: Implements Object#hash so Assets can be used as a Hash key or
# in a Set.
#
# Returns Integer hash of the id.
def hash
id.hash
end
# Public: Compare assets.
#
# Assets are equal if they share the same path and digest.
#
# Returns true or false.
def eql?(other)
self.class == other.class && self.id == other.id
end
alias_method :==, :eql?
end
end
|