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,339 @@
1
+ # frozen_string_literal: true
2
+ require 'json'
3
+ require 'time'
4
+
5
+ require 'concurrent'
6
+
7
+ require 'sprockets/manifest_utils'
8
+
9
+ module Sprockets
10
+ # The Manifest logs the contents of assets compiled to a single directory. It
11
+ # records basic attributes about the asset for fast lookup without having to
12
+ # compile. A pointer from each logical path indicates which fingerprinted
13
+ # asset is the current one.
14
+ #
15
+ # The JSON is part of the public API and should be considered stable. This
16
+ # should make it easy to read from other programming languages and processes
17
+ # that don't have sprockets loaded. See `#assets` and `#files` for more
18
+ # information about the structure.
19
+ class Manifest
20
+ include ManifestUtils
21
+
22
+ attr_reader :environment
23
+
24
+ # Create new Manifest associated with an `environment`. `filename` is a full
25
+ # path to the manifest json file. The file may or may not already exist. The
26
+ # dirname of the `filename` will be used to write compiled assets to.
27
+ # Otherwise, if the path is a directory, the filename will default a random
28
+ # ".sprockets-manifest-*.json" file in that directory.
29
+ #
30
+ # Manifest.new(environment, "./public/assets/manifest.json")
31
+ #
32
+ def initialize(*args)
33
+ if args.first.is_a?(Base) || args.first.nil?
34
+ @environment = args.shift
35
+ end
36
+
37
+ @directory, @filename = args[0], args[1]
38
+
39
+ # Whether the manifest file is using the old manifest-*.json naming convention
40
+ @legacy_manifest = false
41
+
42
+ # Expand paths
43
+ @directory = File.expand_path(@directory) if @directory
44
+ @filename = File.expand_path(@filename) if @filename
45
+
46
+ # If filename is given as the second arg
47
+ if @directory && File.extname(@directory) != ""
48
+ @directory, @filename = nil, @directory
49
+ end
50
+
51
+ # Default dir to the directory of the filename
52
+ @directory ||= File.dirname(@filename) if @filename
53
+
54
+ # If directory is given w/o filename, pick a random manifest location
55
+ if @directory && @filename.nil?
56
+ @filename = find_directory_manifest(@directory, logger)
57
+ end
58
+
59
+ unless @directory && @filename
60
+ raise ArgumentError, "manifest requires output filename"
61
+ end
62
+
63
+ data = {}
64
+
65
+ begin
66
+ if File.exist?(@filename)
67
+ data = json_decode(File.read(@filename))
68
+ end
69
+ rescue JSON::ParserError => e
70
+ logger.error "#{@filename} is invalid: #{e.class} #{e.message}"
71
+ end
72
+
73
+ @data = data
74
+ end
75
+
76
+ # Returns String path to manifest.json file.
77
+ attr_reader :filename
78
+ alias_method :path, :filename
79
+
80
+ attr_reader :directory
81
+ alias_method :dir, :directory
82
+
83
+ # Returns internal assets mapping. Keys are logical paths which
84
+ # map to the latest fingerprinted filename.
85
+ #
86
+ # Logical path (String): Fingerprint path (String)
87
+ #
88
+ # { "application.js" => "application-2e8e9a7c6b0aafa0c9bdeec90ea30213.js",
89
+ # "jquery.js" => "jquery-ae0908555a245f8266f77df5a8edca2e.js" }
90
+ #
91
+ def assets
92
+ @data['assets'] ||= {}
93
+ end
94
+
95
+ # Returns internal file directory listing. Keys are filenames
96
+ # which map to an attributes array.
97
+ #
98
+ # Fingerprint path (String):
99
+ # logical_path: Logical path (String)
100
+ # mtime: ISO8601 mtime (String)
101
+ # digest: Base64 hex digest (String)
102
+ #
103
+ # { "application-2e8e9a7c6b0aafa0c9bdeec90ea30213.js" =>
104
+ # { 'logical_path' => "application.js",
105
+ # 'mtime' => "2011-12-13T21:47:08-06:00",
106
+ # 'digest' => "2e8e9a7c6b0aafa0c9bdeec90ea30213" } }
107
+ #
108
+ def files
109
+ @data['files'] ||= {}
110
+ end
111
+
112
+ # Public: Find all assets matching pattern set in environment.
113
+ #
114
+ # Returns Enumerator of Assets.
115
+ def find(*args, &block)
116
+ unless environment
117
+ raise Error, "manifest requires environment for compilation"
118
+ end
119
+
120
+ return to_enum(__method__, *args) unless block_given?
121
+
122
+ environment = self.environment.cached
123
+ promises = args.flatten.map do |path|
124
+ Concurrent::Promise.execute(executor: executor) do
125
+ environment.find_all_linked_assets(path).to_a
126
+ end
127
+ end
128
+
129
+ promises.each do |promise|
130
+ promise.value!.each(&block)
131
+ end
132
+
133
+ nil
134
+ end
135
+
136
+ # Public: Find the source of assets by paths.
137
+ #
138
+ # Returns Enumerator of assets file content.
139
+ def find_sources(*args)
140
+ return to_enum(__method__, *args) unless block_given?
141
+
142
+ if environment
143
+ find(*args).each do |asset|
144
+ yield asset.source
145
+ end
146
+ else
147
+ args.each do |path|
148
+ asset = assets[path]
149
+ yield File.binread(File.join(dir, asset)) if asset
150
+ end
151
+ end
152
+ end
153
+
154
+ # Compile asset to directory. The asset is written to a
155
+ # fingerprinted filename like
156
+ # `application-2e8e9a7c6b0aafa0c9bdeec90ea30213.js`. An entry is
157
+ # also inserted into the manifest file.
158
+ #
159
+ # compile("application.js")
160
+ #
161
+ def compile(*args)
162
+ unless environment
163
+ raise Error, "manifest requires environment for compilation"
164
+ end
165
+
166
+ filenames = []
167
+ concurrent_exporters = []
168
+
169
+ assets_to_export = Concurrent::Array.new
170
+ find(*args) do |asset|
171
+ assets_to_export << asset
172
+ end
173
+
174
+ assets_to_export.each do |asset|
175
+ mtime = Time.now.iso8601
176
+ files[asset.digest_path] = {
177
+ 'logical_path' => asset.logical_path,
178
+ 'mtime' => mtime,
179
+ 'size' => asset.bytesize,
180
+ 'digest' => asset.hexdigest,
181
+
182
+ # Deprecated: Remove beta integrity attribute in next release.
183
+ # Callers should DigestUtils.hexdigest_integrity_uri to compute the
184
+ # digest themselves.
185
+ 'integrity' => DigestUtils.hexdigest_integrity_uri(asset.hexdigest)
186
+ }
187
+ assets[asset.logical_path] = asset.digest_path
188
+
189
+ filenames << asset.filename
190
+
191
+ promise = nil
192
+ exporters_for_asset(asset) do |exporter|
193
+ next if exporter.skip?(logger)
194
+
195
+ if promise.nil?
196
+ promise = Concurrent::Promise.new(executor: executor) { exporter.call }
197
+ concurrent_exporters << promise.execute
198
+ else
199
+ concurrent_exporters << promise.then { exporter.call }
200
+ end
201
+ end
202
+ end
203
+
204
+ # make sure all exporters have finished before returning the main thread
205
+ concurrent_exporters.each(&:wait!)
206
+ save
207
+
208
+ filenames
209
+ end
210
+
211
+ # Removes file from directory and from manifest. `filename` must
212
+ # be the name with any directory path.
213
+ #
214
+ # manifest.remove("application-2e8e9a7c6b0aafa0c9bdeec90ea30213.js")
215
+ #
216
+ def remove(filename)
217
+ path = File.join(dir, filename)
218
+ gzip = "#{path}.gz"
219
+ logical_path = files[filename]['logical_path']
220
+
221
+ if assets[logical_path] == filename
222
+ assets.delete(logical_path)
223
+ end
224
+
225
+ files.delete(filename)
226
+ FileUtils.rm(path) if File.exist?(path)
227
+ FileUtils.rm(gzip) if File.exist?(gzip)
228
+
229
+ save
230
+
231
+ logger.info "Removed #{filename}"
232
+
233
+ nil
234
+ end
235
+
236
+ # Cleanup old assets in the compile directory. By default it will
237
+ # keep the latest version, 2 backups and any created within the past hour.
238
+ #
239
+ # Examples
240
+ #
241
+ # To force only 1 backup to be kept, set count=1 and age=0.
242
+ #
243
+ # To only keep files created within the last 10 minutes, set count=0 and
244
+ # age=600.
245
+ #
246
+ def clean(count = 2, age = 3600)
247
+ asset_versions = files.group_by { |_, attrs| attrs['logical_path'] }
248
+
249
+ asset_versions.each do |logical_path, versions|
250
+ current = assets[logical_path]
251
+
252
+ versions.reject { |path, _|
253
+ path == current
254
+ }.sort_by { |_, attrs|
255
+ # Sort by timestamp
256
+ Time.parse(attrs['mtime'])
257
+ }.reverse.each_with_index.drop_while { |(_, attrs), index|
258
+ _age = [0, Time.now - Time.parse(attrs['mtime'])].max
259
+ # Keep if under age or within the count limit
260
+ _age < age || index < count
261
+ }.each { |(path, _), _|
262
+ # Remove old assets
263
+ remove(path)
264
+ }
265
+ end
266
+ end
267
+
268
+ # Wipe directive
269
+ def clobber
270
+ FileUtils.rm_r(directory) if File.exist?(directory)
271
+ logger.info "Removed #{directory}"
272
+ # if we have an environment clear the cache too
273
+ environment.cache.clear if environment
274
+ nil
275
+ end
276
+
277
+ # Persist manifest back to FS
278
+ def save
279
+ data = json_encode(@data)
280
+ FileUtils.mkdir_p File.dirname(@filename)
281
+ PathUtils.atomic_write(@filename) do |f|
282
+ f.write(data)
283
+ end
284
+ end
285
+
286
+ private
287
+
288
+ # Given an asset, finds all exporters that
289
+ # match its mime-type.
290
+ #
291
+ # Will yield each expoter to the passed in block.
292
+ #
293
+ # array = []
294
+ # puts asset.content_type # => "application/javascript"
295
+ # exporters_for_asset(asset) do |exporter|
296
+ # array << exporter
297
+ # end
298
+ # # puts array => [Exporters::FileExporter, Exporters::ZlibExporter]
299
+ def exporters_for_asset(asset)
300
+ exporters = [Exporters::FileExporter]
301
+
302
+ environment.exporters.each do |mime_type, exporter_list|
303
+ next unless asset.content_type
304
+ next unless environment.match_mime_type? asset.content_type, mime_type
305
+ exporter_list.each do |exporter|
306
+ exporters << exporter
307
+ end
308
+ end
309
+
310
+ exporters.uniq!
311
+
312
+ exporters.each do |exporter|
313
+ yield exporter.new(asset: asset, environment: environment, directory: dir)
314
+ end
315
+ end
316
+
317
+ def json_decode(obj)
318
+ JSON.parse(obj, create_additions: false)
319
+ end
320
+
321
+ def json_encode(obj)
322
+ JSON.generate(obj)
323
+ end
324
+
325
+ def logger
326
+ if environment
327
+ environment.logger
328
+ else
329
+ logger = Logger.new($stderr)
330
+ logger.level = Logger::FATAL
331
+ logger
332
+ end
333
+ end
334
+
335
+ def executor
336
+ @executor ||= environment.export_concurrent ? :fast : :immediate
337
+ end
338
+ end
339
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+ require 'securerandom'
3
+ require 'logger'
4
+
5
+ module Sprockets
6
+ # Public: Manifest utilities.
7
+ module ManifestUtils
8
+ extend self
9
+
10
+ MANIFEST_RE = /^\.sprockets-manifest-[0-9a-f]{32}.json$/
11
+
12
+ # Public: Generate a new random manifest path.
13
+ #
14
+ # Manifests are not intended to be accessed publicly, but typically live
15
+ # alongside public assets for convenience. To avoid being served, the
16
+ # filename is prefixed with a "." which is usually hidden by web servers
17
+ # like Apache. To help in other environments that may not control this,
18
+ # a random hex string is appended to the filename to prevent people from
19
+ # guessing the location. If directory indexes are enabled on the server,
20
+ # all bets are off.
21
+ #
22
+ # Return String path.
23
+ def generate_manifest_path
24
+ ".sprockets-manifest-#{SecureRandom.hex(16)}.json"
25
+ end
26
+
27
+ # Public: Find or pick a new manifest filename for target build directory.
28
+ #
29
+ # dirname - String dirname
30
+ #
31
+ # Examples
32
+ #
33
+ # find_directory_manifest("/app/public/assets")
34
+ # # => "/app/public/assets/.sprockets-manifest-abc123.json"
35
+ #
36
+ # Returns String filename.
37
+ def find_directory_manifest(dirname, logger = Logger.new($stderr))
38
+ entries = File.directory?(dirname) ? Dir.entries(dirname) : []
39
+ manifest_entries = entries.select { |e| e =~ MANIFEST_RE }
40
+ if manifest_entries.length > 1
41
+ manifest_entries.sort!
42
+ logger.warn("Found multiple manifests: #{manifest_entries}. Choosing the first alphabetically: #{manifest_entries.first}")
43
+ end
44
+ entry = manifest_entries.first || generate_manifest_path
45
+ File.join(dirname, entry)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+ require 'sprockets/encoding_utils'
3
+ require 'sprockets/http_utils'
4
+ require 'sprockets/utils'
5
+
6
+ module Sprockets
7
+ module Mime
8
+ include HTTPUtils, Utils
9
+
10
+ # Public: Mapping of MIME type Strings to properties Hash.
11
+ #
12
+ # key - MIME Type String
13
+ # value - Hash
14
+ # extensions - Array of extnames
15
+ # charset - Default Encoding or function to detect encoding
16
+ #
17
+ # Returns Hash.
18
+ def mime_types
19
+ config[:mime_types]
20
+ end
21
+
22
+ # Internal: Mapping of MIME extension Strings to MIME type Strings.
23
+ #
24
+ # Used for internal fast lookup purposes.
25
+ #
26
+ # Examples:
27
+ #
28
+ # mime_exts['.js'] #=> 'application/javascript'
29
+ #
30
+ # key - MIME extension String
31
+ # value - MIME Type String
32
+ #
33
+ # Returns Hash.
34
+ def mime_exts
35
+ config[:mime_exts]
36
+ end
37
+
38
+ # Public: Register a new mime type.
39
+ #
40
+ # mime_type - String MIME Type
41
+ # extensions - Array of String extnames
42
+ # charset - Proc/Method that detects the charset of a file.
43
+ # See EncodingUtils.
44
+ #
45
+ # Returns nothing.
46
+ def register_mime_type(mime_type, extensions: [], charset: nil)
47
+ extnames = Array(extensions)
48
+
49
+ charset ||= :default if mime_type.start_with?('text/')
50
+ charset = EncodingUtils::CHARSET_DETECT[charset] if charset.is_a?(Symbol)
51
+
52
+ self.config = hash_reassoc(config, :mime_exts) do |mime_exts|
53
+ extnames.each do |extname|
54
+ mime_exts[extname] = mime_type
55
+ end
56
+ mime_exts
57
+ end
58
+
59
+ self.config = hash_reassoc(config, :mime_types) do |mime_types|
60
+ type = { extensions: extnames }
61
+ type[:charset] = charset if charset
62
+ mime_types.merge(mime_type => type)
63
+ end
64
+ end
65
+
66
+ # Internal: Get detecter function for MIME type.
67
+ #
68
+ # mime_type - String MIME type
69
+ #
70
+ # Returns Proc detector or nil if none is available.
71
+ def mime_type_charset_detecter(mime_type)
72
+ if type = config[:mime_types][mime_type]
73
+ if detect = type[:charset]
74
+ return detect
75
+ end
76
+ end
77
+ end
78
+
79
+ # Public: Read file on disk with MIME type specific encoding.
80
+ #
81
+ # filename - String path
82
+ # content_type - String MIME type
83
+ #
84
+ # Returns String file contents transcoded to UTF-8 or in its external
85
+ # encoding.
86
+ def read_file(filename, content_type = nil)
87
+ data = File.binread(filename)
88
+
89
+ if detect = mime_type_charset_detecter(content_type)
90
+ detect.call(data).encode(Encoding::UTF_8, universal_newline: true)
91
+ else
92
+ data
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+ require 'json'
3
+
4
+ module Sprockets
5
+ module Npm
6
+ # Internal: Override resolve_alternates to install package.json behavior.
7
+ #
8
+ # load_path - String environment path
9
+ # logical_path - String path relative to base
10
+ #
11
+ # Returns candidate filenames.
12
+ def resolve_alternates(load_path, logical_path)
13
+ candidates, deps = super
14
+
15
+ dirname = File.join(load_path, logical_path)
16
+
17
+ if directory?(dirname)
18
+ filename = File.join(dirname, 'package.json')
19
+
20
+ if self.file?(filename)
21
+ deps << build_file_digest_uri(filename)
22
+ read_package_directives(dirname, filename) do |path|
23
+ if file?(path)
24
+ candidates << path
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ return candidates, deps
31
+ end
32
+
33
+ # Internal: Read package.json's main and style directives.
34
+ #
35
+ # dirname - String path to component directory.
36
+ # filename - String path to package.json.
37
+ #
38
+ # Returns nothing.
39
+ def read_package_directives(dirname, filename)
40
+ package = JSON.parse(File.read(filename), create_additions: false)
41
+
42
+ case package['main']
43
+ when String
44
+ yield File.expand_path(package['main'], dirname)
45
+ when nil
46
+ yield File.expand_path('index.js', dirname)
47
+ end
48
+
49
+ yield File.expand_path(package['style'], dirname) if package['style']
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+ require 'set'
3
+ require 'sprockets/path_utils'
4
+ require 'sprockets/uri_utils'
5
+
6
+ module Sprockets
7
+ # Internal: Related PathUtils helpers that also track all the file system
8
+ # calls they make for caching purposes. All functions return a standard
9
+ # return value and a Set of cache dependency URIs that can be used in the
10
+ # future to see if the returned value should be invalidated from cache.
11
+ #
12
+ # entries_with_dependencies("app/assets/javascripts")
13
+ # # => [
14
+ # # ["application.js", "projects.js", "users.js", ...]
15
+ # # #<Set: {"file-digest:/path/to/app/assets/javascripts"}>
16
+ # # ]
17
+ #
18
+ # The returned dependency set can be passed to resolve_dependencies(deps)
19
+ # to check if the returned result is still fresh. In this case, entry always
20
+ # returns a single path, but multiple calls should accumulate dependencies
21
+ # into a single set thats saved off and checked later.
22
+ #
23
+ # resolve_dependencies(deps)
24
+ # # => "\x01\x02\x03"
25
+ #
26
+ # Later, resolving the same set again will produce a different hash if
27
+ # something on the file system has changed.
28
+ #
29
+ # resolve_dependencies(deps)
30
+ # # => "\x03\x04\x05"
31
+ #
32
+ module PathDependencyUtils
33
+ include PathUtils
34
+ include URIUtils
35
+
36
+ # Internal: List directory entries and return a set of dependencies that
37
+ # would invalid the cached return result.
38
+ #
39
+ # See PathUtils#entries
40
+ #
41
+ # path - String directory path
42
+ #
43
+ # Returns an Array of entry names and a Set of dependency URIs.
44
+ def entries_with_dependencies(path)
45
+ return entries(path), Set.new([build_file_digest_uri(path)])
46
+ end
47
+
48
+ # Internal: List directory filenames and associated Stats under a
49
+ # directory.
50
+ #
51
+ # See PathUtils#stat_directory
52
+ #
53
+ # dir - A String directory
54
+ #
55
+ # Returns an Array of filenames and a Set of dependency URIs.
56
+ def stat_directory_with_dependencies(dir)
57
+ return stat_directory(dir).to_a, Set.new([build_file_digest_uri(dir)])
58
+ end
59
+
60
+ # Internal: List directory filenames and associated Stats under an entire
61
+ # directory tree.
62
+ #
63
+ # See PathUtils#stat_sorted_tree
64
+ #
65
+ # dir - A String directory
66
+ #
67
+ # Returns an Array of filenames and a Set of dependency URIs.
68
+ def stat_sorted_tree_with_dependencies(dir)
69
+ deps = Set.new([build_file_digest_uri(dir)])
70
+ results = stat_sorted_tree(dir).map do |path, stat|
71
+ deps << build_file_digest_uri(path) if stat.directory?
72
+ [path, stat]
73
+ end
74
+ return results, deps
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+ require 'sprockets/digest_utils'
3
+ require 'sprockets/path_utils'
4
+
5
+ module Sprockets
6
+ # Internal: Crossover of path and digest utilities functions.
7
+ module PathDigestUtils
8
+ include DigestUtils, PathUtils
9
+
10
+ # Internal: Compute digest for file stat.
11
+ #
12
+ # path - String filename
13
+ # stat - File::Stat
14
+ #
15
+ # Returns String digest bytes.
16
+ def stat_digest(path, stat)
17
+ if stat.directory?
18
+ # If its a directive, digest the list of filenames
19
+ digest_class.digest(self.entries(path).join(','.freeze))
20
+ elsif stat.file?
21
+ # If its a file, digest the contents
22
+ digest_class.file(path.to_s).digest
23
+ else
24
+ raise TypeError, "stat was not a directory or file: #{stat.ftype}"
25
+ end
26
+ end
27
+
28
+ # Internal: Compute digest for path.
29
+ #
30
+ # path - String filename or directory path.
31
+ #
32
+ # Returns String digest bytes or nil.
33
+ def file_digest(path)
34
+ if stat = self.stat(path)
35
+ self.stat_digest(path, stat)
36
+ end
37
+ end
38
+
39
+ # Internal: Compute digest for a set of paths.
40
+ #
41
+ # paths - Array of filename or directory paths.
42
+ #
43
+ # Returns String digest bytes.
44
+ def files_digest(paths)
45
+ self.digest(paths.map { |path| self.file_digest(path) })
46
+ end
47
+ end
48
+ end