lib/roda/plugins/assets.rb in roda-3.41.0 vs lib/roda/plugins/assets.rb in roda-3.42.0
- old
+ new
@@ -374,11 +374,11 @@
s.empty? ? s : (s + '/').freeze
end
if opts[:precompiled] && !opts[:compiled] && ::File.exist?(opts[:precompiled])
require 'json'
- opts[:compiled] = (app.opts[:json_parser] || ::JSON.method(:parse)).call(::File.read(opts[:precompiled]))
+ opts[:compiled] = app.send(:_precompiled_asset_metadata, opts[:precompiled])
end
if opts[:early_hints]
app.plugin :early_hints
end
@@ -453,31 +453,38 @@
# compile assets for the given asset group.
def compile_assets(type=nil)
require 'fileutils'
unless assets_opts[:compiled]
- opts[:assets] = assets_opts.merge(:compiled => {})
+ opts[:assets] = assets_opts.merge(:compiled => _compiled_assets_initial_hash).freeze
end
if type == nil
_compile_assets(:css)
_compile_assets(:js)
else
_compile_assets(type)
end
- if assets_opts[:precompiled]
+ if precompile_file = assets_opts[:precompiled]
require 'json'
- ::FileUtils.mkdir_p(File.dirname(assets_opts[:precompiled]))
- ::File.open(assets_opts[:precompiled], 'wb'){|f| f.write((opts[:json_serializer] || :to_json.to_proc).call(assets_opts[:compiled]))}
+ ::FileUtils.mkdir_p(File.dirname(precompile_file))
+ tmp_file = "#{precompile_file}.tmp"
+ ::File.open(tmp_file, 'wb'){|f| f.write((opts[:json_serializer] || :to_json.to_proc).call(assets_opts[:compiled]))}
+ ::File.rename(tmp_file, precompile_file)
end
assets_opts[:compiled]
end
private
+ # The initial hash to use to store compiled asset metadata.
+ def _compiled_assets_initial_hash
+ {}
+ end
+
# Internals of compile_assets, handling recursive calls for loading
# all asset groups under the given type.
def _compile_assets(type)
type, *dirs = type if type.is_a?(Array)
dirs ||= []
@@ -491,10 +498,15 @@
files = Array(files)
compile_assets_files(files, type, dirs) unless files.empty?
end
end
+ # The precompiled asset metadata stored in the given file
+ def _precompiled_asset_metadata(file)
+ (opts[:json_parser] || ::JSON.method(:parse)).call(::File.read(file))
+ end
+
# Compile each array of files for the given type into a single
# file. Dirs should be an array of asset group names, if these
# are files in an asset group.
def compile_assets_files(files, type, dirs)
dirs = nil if dirs && dirs.empty?
@@ -792,26 +804,35 @@
module RequestClassMethods
# An array of asset type strings and regexps for that type, for all asset types
# handled.
def assets_matchers
@assets_matchers ||= [:css, :js].map do |t|
- [t, assets_regexp(t)].freeze if roda_class.assets_opts[t]
+ if regexp = assets_regexp(t)
+ [t, regexp].freeze
+ end
end.compact.freeze
end
private
+ # A string for the asset filename for the asset type, key, and digest.
+ def _asset_regexp(type, key, digest)
+ "#{key.sub(/\A#{type}/, '')}.#{digest}.#{type}"
+ end
+
# The regexp matcher to use for the given type. This handles any asset groups
# for the asset types.
def assets_regexp(type)
o = roda_class.assets_opts
if compiled = o[:compiled]
- assets = compiled.select{|k,_| k =~ /\A#{type}/}.map do |k, md|
- "#{k.sub(/\A#{type}/, '')}.#{md}.#{type}"
- end
+ assets = compiled.
+ select{|k,_| k =~ /\A#{type}/}.
+ map{|k, md| _asset_regexp(type, k, md)}
+ return if assets.empty?
/#{o[:"compiled_#{type}_prefix"]}(#{Regexp.union(assets)})/
else
- assets = unnest_assets_hash(o[type])
+ return unless assets = o[type]
+ assets = unnest_assets_hash(assets)
ts = o[:timestamp_paths]
/#{o[:"#{type}_prefix"]}#{"\\d+#{ts}" if ts}(#{Regexp.union(assets.uniq)})#{o[:"#{type}_suffix"]}/
end
end