giga-lite-hub 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/giga-lite-hub.gemspec +12 -0
  3. data/sprockets-4.2.2/CHANGELOG.md +118 -0
  4. data/sprockets-4.2.2/MIT-LICENSE +21 -0
  5. data/sprockets-4.2.2/README.md +716 -0
  6. data/sprockets-4.2.2/bin/sprockets +93 -0
  7. data/sprockets-4.2.2/lib/rake/sprocketstask.rb +157 -0
  8. data/sprockets-4.2.2/lib/sprockets/add_source_map_comment_to_asset_processor.rb +60 -0
  9. data/sprockets-4.2.2/lib/sprockets/asset.rb +212 -0
  10. data/sprockets-4.2.2/lib/sprockets/autoload/babel.rb +8 -0
  11. data/sprockets-4.2.2/lib/sprockets/autoload/closure.rb +8 -0
  12. data/sprockets-4.2.2/lib/sprockets/autoload/coffee_script.rb +8 -0
  13. data/sprockets-4.2.2/lib/sprockets/autoload/eco.rb +8 -0
  14. data/sprockets-4.2.2/lib/sprockets/autoload/ejs.rb +8 -0
  15. data/sprockets-4.2.2/lib/sprockets/autoload/jsminc.rb +8 -0
  16. data/sprockets-4.2.2/lib/sprockets/autoload/sass.rb +8 -0
  17. data/sprockets-4.2.2/lib/sprockets/autoload/sassc.rb +8 -0
  18. data/sprockets-4.2.2/lib/sprockets/autoload/uglifier.rb +8 -0
  19. data/sprockets-4.2.2/lib/sprockets/autoload/yui.rb +8 -0
  20. data/sprockets-4.2.2/lib/sprockets/autoload/zopfli.rb +7 -0
  21. data/sprockets-4.2.2/lib/sprockets/autoload.rb +16 -0
  22. data/sprockets-4.2.2/lib/sprockets/babel_processor.rb +66 -0
  23. data/sprockets-4.2.2/lib/sprockets/base.rb +147 -0
  24. data/sprockets-4.2.2/lib/sprockets/bower.rb +61 -0
  25. data/sprockets-4.2.2/lib/sprockets/bundle.rb +105 -0
  26. data/sprockets-4.2.2/lib/sprockets/cache/file_store.rb +208 -0
  27. data/sprockets-4.2.2/lib/sprockets/cache/memory_store.rb +84 -0
  28. data/sprockets-4.2.2/lib/sprockets/cache/null_store.rb +54 -0
  29. data/sprockets-4.2.2/lib/sprockets/cache.rb +271 -0
  30. data/sprockets-4.2.2/lib/sprockets/cached_environment.rb +64 -0
  31. data/sprockets-4.2.2/lib/sprockets/closure_compressor.rb +48 -0
  32. data/sprockets-4.2.2/lib/sprockets/coffee_script_processor.rb +39 -0
  33. data/sprockets-4.2.2/lib/sprockets/compressing.rb +134 -0
  34. data/sprockets-4.2.2/lib/sprockets/configuration.rb +79 -0
  35. data/sprockets-4.2.2/lib/sprockets/context.rb +305 -0
  36. data/sprockets-4.2.2/lib/sprockets/dependencies.rb +74 -0
  37. data/sprockets-4.2.2/lib/sprockets/digest_utils.rb +197 -0
  38. data/sprockets-4.2.2/lib/sprockets/directive_processor.rb +432 -0
  39. data/sprockets-4.2.2/lib/sprockets/eco_processor.rb +33 -0
  40. data/sprockets-4.2.2/lib/sprockets/ejs_processor.rb +32 -0
  41. data/sprockets-4.2.2/lib/sprockets/encoding_utils.rb +261 -0
  42. data/sprockets-4.2.2/lib/sprockets/environment.rb +46 -0
  43. data/sprockets-4.2.2/lib/sprockets/erb_processor.rb +43 -0
  44. data/sprockets-4.2.2/lib/sprockets/errors.rb +12 -0
  45. data/sprockets-4.2.2/lib/sprockets/exporters/base.rb +71 -0
  46. data/sprockets-4.2.2/lib/sprockets/exporters/file_exporter.rb +24 -0
  47. data/sprockets-4.2.2/lib/sprockets/exporters/zlib_exporter.rb +33 -0
  48. data/sprockets-4.2.2/lib/sprockets/exporters/zopfli_exporter.rb +14 -0
  49. data/sprockets-4.2.2/lib/sprockets/exporting.rb +73 -0
  50. data/sprockets-4.2.2/lib/sprockets/file_reader.rb +16 -0
  51. data/sprockets-4.2.2/lib/sprockets/http_utils.rb +135 -0
  52. data/sprockets-4.2.2/lib/sprockets/jsminc_compressor.rb +32 -0
  53. data/sprockets-4.2.2/lib/sprockets/jst_processor.rb +50 -0
  54. data/sprockets-4.2.2/lib/sprockets/loader.rb +347 -0
  55. data/sprockets-4.2.2/lib/sprockets/manifest.rb +339 -0
  56. data/sprockets-4.2.2/lib/sprockets/manifest_utils.rb +48 -0
  57. data/sprockets-4.2.2/lib/sprockets/mime.rb +96 -0
  58. data/sprockets-4.2.2/lib/sprockets/npm.rb +52 -0
  59. data/sprockets-4.2.2/lib/sprockets/path_dependency_utils.rb +77 -0
  60. data/sprockets-4.2.2/lib/sprockets/path_digest_utils.rb +48 -0
  61. data/sprockets-4.2.2/lib/sprockets/path_utils.rb +367 -0
  62. data/sprockets-4.2.2/lib/sprockets/paths.rb +82 -0
  63. data/sprockets-4.2.2/lib/sprockets/preprocessors/default_source_map.rb +49 -0
  64. data/sprockets-4.2.2/lib/sprockets/processing.rb +228 -0
  65. data/sprockets-4.2.2/lib/sprockets/processor_utils.rb +170 -0
  66. data/sprockets-4.2.2/lib/sprockets/resolve.rb +295 -0
  67. data/sprockets-4.2.2/lib/sprockets/sass_cache_store.rb +30 -0
  68. data/sprockets-4.2.2/lib/sprockets/sass_compressor.rb +63 -0
  69. data/sprockets-4.2.2/lib/sprockets/sass_functions.rb +3 -0
  70. data/sprockets-4.2.2/lib/sprockets/sass_importer.rb +3 -0
  71. data/sprockets-4.2.2/lib/sprockets/sass_processor.rb +313 -0
  72. data/sprockets-4.2.2/lib/sprockets/sassc_compressor.rb +56 -0
  73. data/sprockets-4.2.2/lib/sprockets/sassc_processor.rb +297 -0
  74. data/sprockets-4.2.2/lib/sprockets/server.rb +315 -0
  75. data/sprockets-4.2.2/lib/sprockets/source_map_processor.rb +66 -0
  76. data/sprockets-4.2.2/lib/sprockets/source_map_utils.rb +483 -0
  77. data/sprockets-4.2.2/lib/sprockets/transformers.rb +173 -0
  78. data/sprockets-4.2.2/lib/sprockets/uglifier_compressor.rb +66 -0
  79. data/sprockets-4.2.2/lib/sprockets/unloaded_asset.rb +139 -0
  80. data/sprockets-4.2.2/lib/sprockets/uri_tar.rb +99 -0
  81. data/sprockets-4.2.2/lib/sprockets/uri_utils.rb +194 -0
  82. data/sprockets-4.2.2/lib/sprockets/utils/gzip.rb +99 -0
  83. data/sprockets-4.2.2/lib/sprockets/utils.rb +210 -0
  84. data/sprockets-4.2.2/lib/sprockets/version.rb +4 -0
  85. data/sprockets-4.2.2/lib/sprockets/yui_compressor.rb +56 -0
  86. data/sprockets-4.2.2/lib/sprockets.rb +232 -0
  87. metadata +126 -0
@@ -0,0 +1,305 @@
1
+ # frozen_string_literal: true
2
+ require 'rack/utils'
3
+ require 'set'
4
+ require 'sprockets/errors'
5
+ require 'delegate'
6
+
7
+ module Sprockets
8
+ # They are typically accessed by ERB templates. You can mix in custom helpers
9
+ # by injecting them into `Environment#context_class`. Do not mix them into
10
+ # `Context` directly.
11
+ #
12
+ # environment.context_class.class_eval do
13
+ # include MyHelper
14
+ # def asset_url; end
15
+ # end
16
+ #
17
+ # <%= asset_url "foo.png" %>
18
+ #
19
+ # The `Context` also collects dependencies declared by
20
+ # assets. See `DirectiveProcessor` for an example of this.
21
+ class Context
22
+ # Internal: Proxy for ENV that keeps track of the environment variables used
23
+ class ENVProxy < SimpleDelegator
24
+ def initialize(context)
25
+ @context = context
26
+ super(ENV)
27
+ end
28
+
29
+ def [](key)
30
+ @context.depend_on_env(key)
31
+ super
32
+ end
33
+
34
+ def fetch(key, *)
35
+ @context.depend_on_env(key)
36
+ super
37
+ end
38
+ end
39
+
40
+ attr_reader :environment, :filename
41
+
42
+ def initialize(input)
43
+ @environment = input[:environment]
44
+ @metadata = input[:metadata]
45
+ @load_path = input[:load_path]
46
+ @logical_path = input[:name]
47
+ @filename = input[:filename]
48
+ @dirname = File.dirname(@filename)
49
+ @content_type = input[:content_type]
50
+
51
+ @required = Set.new(@metadata[:required])
52
+ @stubbed = Set.new(@metadata[:stubbed])
53
+ @links = Set.new(@metadata[:links])
54
+ @dependencies = Set.new(input[:metadata][:dependencies])
55
+ end
56
+
57
+ def metadata
58
+ { required: @required,
59
+ stubbed: @stubbed,
60
+ links: @links,
61
+ dependencies: @dependencies }
62
+ end
63
+
64
+ def env_proxy
65
+ ENVProxy.new(self)
66
+ end
67
+
68
+ # Returns the environment path that contains the file.
69
+ #
70
+ # If `app/javascripts` and `app/stylesheets` are in your path, and
71
+ # current file is `app/javascripts/foo/bar.js`, `load_path` would
72
+ # return `app/javascripts`.
73
+ attr_reader :load_path
74
+ alias_method :root_path, :load_path
75
+
76
+ # Returns logical path without any file extensions.
77
+ #
78
+ # 'app/javascripts/application.js'
79
+ # # => 'application'
80
+ #
81
+ attr_reader :logical_path
82
+
83
+ # Returns content type of file
84
+ #
85
+ # 'application/javascript'
86
+ # 'text/css'
87
+ #
88
+ attr_reader :content_type
89
+
90
+ # Public: Given a logical path, `resolve` will find and return an Asset URI.
91
+ # Relative paths will also be resolved. An accept type maybe given to
92
+ # restrict the search.
93
+ #
94
+ # resolve("foo.js")
95
+ # # => "file:///path/to/app/javascripts/foo.js?type=application/javascript"
96
+ #
97
+ # resolve("./bar.js")
98
+ # # => "file:///path/to/app/javascripts/bar.js?type=application/javascript"
99
+ #
100
+ # path - String logical or absolute path
101
+ # accept - String content accept type
102
+ #
103
+ # Returns an Asset URI String.
104
+ def resolve(path, **kargs)
105
+ kargs[:base_path] = @dirname
106
+ uri, deps = environment.resolve!(path, **kargs)
107
+ @dependencies.merge(deps)
108
+ uri
109
+ end
110
+
111
+ # Public: Load Asset by AssetURI and track it as a dependency.
112
+ #
113
+ # uri - AssetURI
114
+ #
115
+ # Returns Asset.
116
+ def load(uri)
117
+ asset = environment.load(uri)
118
+ @dependencies.merge(asset.metadata[:dependencies])
119
+ asset
120
+ end
121
+
122
+ # `depend_on` allows you to state a dependency on a file without
123
+ # including it.
124
+ #
125
+ # This is used for caching purposes. Any changes made to
126
+ # the dependency file will invalidate the cache of the
127
+ # source file.
128
+ def depend_on(path)
129
+ if environment.absolute_path?(path) && environment.stat(path)
130
+ @dependencies << environment.build_file_digest_uri(path)
131
+ else
132
+ resolve(path)
133
+ end
134
+ nil
135
+ end
136
+
137
+ # `depend_on_asset` allows you to state an asset dependency
138
+ # without including it.
139
+ #
140
+ # This is used for caching purposes. Any changes that would
141
+ # invalidate the dependency asset will invalidate the source
142
+ # file. Unlike `depend_on`, this will recursively include
143
+ # the target asset's dependencies.
144
+ def depend_on_asset(path)
145
+ load(resolve(path))
146
+ end
147
+
148
+ # `depend_on_env` allows you to state a dependency on an environment
149
+ # variable.
150
+ #
151
+ # This is used for caching purposes. Any changes in the value of the
152
+ # environment variable will invalidate the cache of the source file.
153
+ def depend_on_env(key)
154
+ @dependencies << "env:#{key}"
155
+ end
156
+
157
+ # `require_asset` declares `path` as a dependency of the file. The
158
+ # dependency will be inserted before the file and will only be
159
+ # included once.
160
+ #
161
+ # If ERB processing is enabled, you can use it to dynamically
162
+ # require assets.
163
+ #
164
+ # <%= require_asset "#{framework}.js" %>
165
+ #
166
+ def require_asset(path)
167
+ @required << resolve(path, accept: @content_type, pipeline: :self)
168
+ nil
169
+ end
170
+
171
+ # `stub_asset` blacklists `path` from being included in the bundle.
172
+ # `path` must be an asset which may or may not already be included
173
+ # in the bundle.
174
+ def stub_asset(path)
175
+ @stubbed << resolve(path, accept: @content_type, pipeline: :self)
176
+ nil
177
+ end
178
+
179
+ # `link_asset` declares an external dependency on an asset without directly
180
+ # including it. The target asset is returned from this function making it
181
+ # easy to construct a link to it.
182
+ #
183
+ # Returns an Asset or nil.
184
+ def link_asset(path)
185
+ asset = depend_on_asset(path)
186
+ @links << asset.uri
187
+ asset
188
+ end
189
+
190
+ # Returns a `data:` URI with the contents of the asset at the specified
191
+ # path, and marks that path as a dependency of the current file.
192
+ #
193
+ # Uses URI encoding for SVG files, base64 encoding for all the other files.
194
+ #
195
+ # Use `asset_data_uri` from ERB with CSS or JavaScript assets:
196
+ #
197
+ # #logo { background: url(<%= asset_data_uri 'logo.png' %>) }
198
+ #
199
+ # $('<img>').attr('src', '<%= asset_data_uri 'avatar.jpg' %>')
200
+ #
201
+ def asset_data_uri(path)
202
+ asset = depend_on_asset(path)
203
+ if asset.content_type == 'image/svg+xml'
204
+ svg_asset_data_uri(asset)
205
+ else
206
+ base64_asset_data_uri(asset)
207
+ end
208
+ end
209
+
210
+ # Expands logical path to full url to asset.
211
+ #
212
+ # NOTE: This helper is currently not implemented and should be
213
+ # customized by the application. Though, in the future, some
214
+ # basic implementation may be provided with different methods that
215
+ # are required to be overridden.
216
+ def asset_path(path, options = {})
217
+ message = <<-EOS
218
+ Custom asset_path helper is not implemented
219
+
220
+ Extend your environment context with a custom method.
221
+
222
+ environment.context_class.class_eval do
223
+ def asset_path(path, options = {})
224
+ end
225
+ end
226
+ EOS
227
+ raise NotImplementedError, message
228
+ end
229
+
230
+ # Expand logical image asset path.
231
+ def image_path(path)
232
+ asset_path(path, type: :image)
233
+ end
234
+
235
+ # Expand logical video asset path.
236
+ def video_path(path)
237
+ asset_path(path, type: :video)
238
+ end
239
+
240
+ # Expand logical audio asset path.
241
+ def audio_path(path)
242
+ asset_path(path, type: :audio)
243
+ end
244
+
245
+ # Expand logical font asset path.
246
+ def font_path(path)
247
+ asset_path(path, type: :font)
248
+ end
249
+
250
+ # Expand logical javascript asset path.
251
+ def javascript_path(path)
252
+ asset_path(path, type: :javascript)
253
+ end
254
+
255
+ # Expand logical stylesheet asset path.
256
+ def stylesheet_path(path)
257
+ asset_path(path, type: :stylesheet)
258
+ end
259
+
260
+ protected
261
+
262
+ # Returns a URI-encoded data URI (always "-quoted).
263
+ def svg_asset_data_uri(asset)
264
+ svg = asset.source.dup
265
+ optimize_svg_for_uri_escaping!(svg)
266
+ data = Rack::Utils.escape(svg)
267
+ optimize_quoted_uri_escapes!(data)
268
+ "\"data:#{asset.content_type};charset=utf-8,#{data}\""
269
+ end
270
+
271
+ # Returns a Base64-encoded data URI.
272
+ def base64_asset_data_uri(asset)
273
+ data = Rack::Utils.escape(EncodingUtils.base64(asset.source))
274
+ "data:#{asset.content_type};base64,#{data}"
275
+ end
276
+
277
+ # Optimizes an SVG for being URI-escaped.
278
+ #
279
+ # This method only performs these basic but crucial optimizations:
280
+ # * Replaces " with ', because ' does not need escaping.
281
+ # * Removes comments, meta, doctype, and newlines.
282
+ # * Collapses whitespace.
283
+ def optimize_svg_for_uri_escaping!(svg)
284
+ # Remove comments, xml meta, and doctype
285
+ svg.gsub!(/<!--.*?-->|<\?.*?\?>|<!.*?>/m, '')
286
+ # Replace consecutive whitespace and newlines with a space
287
+ svg.gsub!(/\s+/, ' ')
288
+ # Collapse inter-tag whitespace
289
+ svg.gsub!('> <', '><')
290
+ # Replace " with '
291
+ svg.gsub!(/([\w:])="(.*?)"/, "\\1='\\2'")
292
+ svg.strip!
293
+ end
294
+
295
+ # Un-escapes characters in the given URI-escaped string that do not need
296
+ # escaping in "-quoted data URIs.
297
+ def optimize_quoted_uri_escapes!(escaped)
298
+ escaped.gsub!('%3D', '=')
299
+ escaped.gsub!('%3A', ':')
300
+ escaped.gsub!('%2F', '/')
301
+ escaped.gsub!('%27', "'")
302
+ escaped.tr!('+', ' ')
303
+ end
304
+ end
305
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+ require 'sprockets/digest_utils'
3
+ require 'sprockets/path_digest_utils'
4
+ require 'sprockets/uri_utils'
5
+
6
+ module Sprockets
7
+ # `Dependencies` is an internal mixin whose public methods are exposed on the
8
+ # `Environment` and `CachedEnvironment` classes.
9
+ module Dependencies
10
+ include DigestUtils, PathDigestUtils, URIUtils
11
+
12
+ # Public: Mapping dependency schemes to resolver functions.
13
+ #
14
+ # key - String scheme
15
+ # value - Proc.call(Environment, String)
16
+ #
17
+ # Returns Hash.
18
+ def dependency_resolvers
19
+ config[:dependency_resolvers]
20
+ end
21
+
22
+ # Public: Default set of dependency URIs for assets.
23
+ #
24
+ # Returns Set of String URIs.
25
+ def dependencies
26
+ config[:dependencies]
27
+ end
28
+
29
+ # Public: Register new dependency URI resolver.
30
+ #
31
+ # scheme - String scheme
32
+ # block -
33
+ # environment - Environment
34
+ # uri - String dependency URI
35
+ #
36
+ # Returns nothing.
37
+ def register_dependency_resolver(scheme, &block)
38
+ self.config = hash_reassoc(config, :dependency_resolvers) do |hash|
39
+ hash.merge(scheme => block)
40
+ end
41
+ end
42
+
43
+ # Public: Add environmental dependency inherited by all assets.
44
+ #
45
+ # uri - String dependency URI
46
+ #
47
+ # Returns nothing.
48
+ def add_dependency(uri)
49
+ self.config = hash_reassoc(config, :dependencies) do |set|
50
+ set + Set.new([uri])
51
+ end
52
+ end
53
+ alias_method :depend_on, :add_dependency
54
+
55
+ # Internal: Resolve dependency URIs.
56
+ #
57
+ # Returns resolved Object.
58
+ def resolve_dependency(str)
59
+ # Optimize for the most common scheme to
60
+ # save 22k allocations on an average Spree app.
61
+ scheme = if str.start_with?('file-digest:'.freeze)
62
+ 'file-digest'.freeze
63
+ else
64
+ str[/([^:]+)/, 1]
65
+ end
66
+
67
+ if resolver = config[:dependency_resolvers][scheme]
68
+ resolver.call(self, str)
69
+ else
70
+ nil
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+ require 'digest/sha1'
3
+ require 'digest/sha2'
4
+ require 'set'
5
+
6
+ module Sprockets
7
+ # Internal: Hash functions and digest related utilities. Mixed into
8
+ # Environment.
9
+ module DigestUtils
10
+ extend self
11
+
12
+ # Internal: Default digest class.
13
+ #
14
+ # Returns a Digest::Base subclass.
15
+ def digest_class
16
+ Digest::SHA256
17
+ end
18
+
19
+ # Internal: Maps digest bytesize to the digest class.
20
+ DIGEST_SIZES = {
21
+ 20 => Digest::SHA1,
22
+ 32 => Digest::SHA256,
23
+ 48 => Digest::SHA384,
24
+ 64 => Digest::SHA512
25
+ }
26
+
27
+ # Internal: Detect digest class hash algorithm for digest bytes.
28
+ #
29
+ # While not elegant, all the supported digests have a unique bytesize.
30
+ #
31
+ # Returns Digest::Base or nil.
32
+ def detect_digest_class(bytes)
33
+ DIGEST_SIZES[bytes.bytesize]
34
+ end
35
+
36
+ ADD_VALUE_TO_DIGEST = {
37
+ String => ->(val, digest) { digest << val },
38
+ FalseClass => ->(val, digest) { digest << 'FalseClass'.freeze },
39
+ TrueClass => ->(val, digest) { digest << 'TrueClass'.freeze },
40
+ NilClass => ->(val, digest) { digest << 'NilClass'.freeze },
41
+
42
+ Symbol => ->(val, digest) {
43
+ digest << 'Symbol'.freeze
44
+ digest << val.to_s
45
+ },
46
+ Integer => ->(val, digest) {
47
+ digest << 'Integer'.freeze
48
+ digest << val.to_s
49
+ },
50
+ Array => ->(val, digest) {
51
+ digest << 'Array'.freeze
52
+ val.each do |element|
53
+ ADD_VALUE_TO_DIGEST[element.class].call(element, digest)
54
+ end
55
+ },
56
+ Hash => ->(val, digest) {
57
+ digest << 'Hash'.freeze
58
+ val.sort.each do |array|
59
+ ADD_VALUE_TO_DIGEST[Array].call(array, digest)
60
+ end
61
+ },
62
+ Set => ->(val, digest) {
63
+ digest << 'Set'.freeze
64
+ ADD_VALUE_TO_DIGEST[Array].call(val, digest)
65
+ },
66
+ Encoding => ->(val, digest) {
67
+ digest << 'Encoding'.freeze
68
+ digest << val.name
69
+ }
70
+ }
71
+
72
+ ADD_VALUE_TO_DIGEST.compare_by_identity.rehash
73
+
74
+ ADD_VALUE_TO_DIGEST.default_proc = ->(_, val) {
75
+ raise TypeError, "couldn't digest #{ val }"
76
+ }
77
+ private_constant :ADD_VALUE_TO_DIGEST
78
+
79
+ # Internal: Generate a hexdigest for a nested JSON serializable object.
80
+ #
81
+ # This is used for generating cache keys, so its pretty important its
82
+ # wicked fast. Microbenchmarks away!
83
+ #
84
+ # obj - A JSON serializable object.
85
+ #
86
+ # Returns a String digest of the object.
87
+ def digest(obj)
88
+ build_digest(obj).digest
89
+ end
90
+
91
+ # Internal: Generate a hexdigest for a nested JSON serializable object.
92
+ #
93
+ # The same as `pack_hexdigest(digest(obj))`.
94
+ #
95
+ # obj - A JSON serializable object.
96
+ #
97
+ # Returns a String digest of the object.
98
+ def hexdigest(obj)
99
+ build_digest(obj).hexdigest!
100
+ end
101
+
102
+ # Internal: Pack a binary digest to a hex encoded string.
103
+ #
104
+ # bin - String bytes
105
+ #
106
+ # Returns hex String.
107
+ def pack_hexdigest(bin)
108
+ bin.unpack('H*'.freeze).first
109
+ end
110
+
111
+ # Internal: Unpack a hex encoded digest string into binary bytes.
112
+ #
113
+ # hex - String hex
114
+ #
115
+ # Returns binary String.
116
+ def unpack_hexdigest(hex)
117
+ [hex].pack('H*')
118
+ end
119
+
120
+ # Internal: Pack a binary digest to a base64 encoded string.
121
+ #
122
+ # bin - String bytes
123
+ #
124
+ # Returns base64 String.
125
+ def pack_base64digest(bin)
126
+ [bin].pack('m0')
127
+ end
128
+
129
+ # Internal: Pack a binary digest to a urlsafe base64 encoded string.
130
+ #
131
+ # bin - String bytes
132
+ #
133
+ # Returns urlsafe base64 String.
134
+ def pack_urlsafe_base64digest(bin)
135
+ str = pack_base64digest(bin)
136
+ str.tr!('+/'.freeze, '-_'.freeze)
137
+ str.tr!('='.freeze, ''.freeze)
138
+ str
139
+ end
140
+
141
+ # Internal: Maps digest class to the CSP hash algorithm name.
142
+ HASH_ALGORITHMS = {
143
+ Digest::SHA256 => 'sha256'.freeze,
144
+ Digest::SHA384 => 'sha384'.freeze,
145
+ Digest::SHA512 => 'sha512'.freeze
146
+ }
147
+
148
+ # Public: Generate hash for use in the `integrity` attribute of an asset tag
149
+ # as per the subresource integrity specification.
150
+ #
151
+ # digest - The String byte digest of the asset content.
152
+ #
153
+ # Returns a String or nil if hash algorithm is incompatible.
154
+ def integrity_uri(digest)
155
+ case digest
156
+ when Digest::Base
157
+ digest_class = digest.class
158
+ digest = digest.digest
159
+ when String
160
+ digest_class = DIGEST_SIZES[digest.bytesize]
161
+ else
162
+ raise TypeError, "unknown digest: #{digest.inspect}"
163
+ end
164
+
165
+ if hash_name = HASH_ALGORITHMS[digest_class]
166
+ "#{hash_name}-#{pack_base64digest(digest)}"
167
+ end
168
+ end
169
+
170
+ # Public: Generate hash for use in the `integrity` attribute of an asset tag
171
+ # as per the subresource integrity specification.
172
+ #
173
+ # digest - The String hexbyte digest of the asset content.
174
+ #
175
+ # Returns a String or nil if hash algorithm is incompatible.
176
+ def hexdigest_integrity_uri(hexdigest)
177
+ integrity_uri(unpack_hexdigest(hexdigest))
178
+ end
179
+
180
+ # Internal: Checks an asset name for a valid digest
181
+ #
182
+ # name - The name of the asset
183
+ #
184
+ # Returns true if the name contains a digest like string and .digested before the extension
185
+ def already_digested?(name)
186
+ return name =~ /-([0-9a-zA-Z]{7,128})\.digested/
187
+ end
188
+
189
+ private
190
+ def build_digest(obj)
191
+ digest = digest_class.new
192
+
193
+ ADD_VALUE_TO_DIGEST[obj.class].call(obj, digest)
194
+ digest
195
+ end
196
+ end
197
+ end