module Roda::RodaPlugins::Assets::ClassMethods
def _compile_assets(type)
Internals of compile_assets, handling recursive calls for loading
def _compile_assets(type) type, *dirs = type if type.is_a?(Array) dirs ||= [] files = assets_opts[type] dirs.each{|d| files = files[d]} case files when Hash files.each_key{|dir| _compile_assets([type] + dirs + [dir])} else files = Array(files) compile_assets_files(files, type, dirs) unless files.empty? end end
def _compiled_assets_initial_hash
def _compiled_assets_initial_hash {} end
def _precompiled_asset_metadata(file)
def _precompiled_asset_metadata(file) (opts[:json_parser] || ::JSON.method(:parse)).call(::File.read(file)) end
def asset_digest(content)
a different digest type or to return a static string if you don't
SHA256 hash of the content. This method can be overridden to use
Return a unique id for the given content. By default, uses the
def asset_digest(content) algo = assets_opts[:sri] || :sha256 digest = begin require 'openssl' ::OpenSSL::Digest # :nocov: rescue LoadError require 'digest/sha2' ::Digest # :nocov: end digest.const_get(algo.to_s.upcase).hexdigest(content) end
def assets_opts
def assets_opts opts[:assets] end
def compile_assets(type=nil)
can specify an array of types (e.g. [:css, :frontend]) to
is given, compile both the :css and :js asset types. You
Compile options for the given asset type. If no asset_type
def compile_assets(type=nil) require 'fileutils' unless assets_opts[: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 precompile_file = assets_opts[:precompiled] require 'json' ::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
def compile_assets_files(files, type, dirs)
file. Dirs should be an array of asset group names, if these
Compile each array of files for the given type into a single
def compile_assets_files(files, type, dirs) dirs = nil if dirs && dirs.empty? o = assets_opts app = allocate content = files.map do |file| file = "#{dirs.join('/')}/#{file}" if dirs && o[:group_subdirs] file = "#{o[:"#{type}_path"]}#{file}" app.read_asset_file(file, type) end.join("\n") unless o[:concat_only] content = compress_asset(content, type) end suffix = ".#{dirs.join('.')}" if dirs key = "#{type}#{suffix}" unique_id = o[:compiled][key] = asset_digest(content) path = "#{o[:"compiled_#{type}_path"]}#{suffix}.#{unique_id}.#{type}" ::FileUtils.mkdir_p(File.dirname(path)) ::File.open(path, 'wb'){|f| f.write(content)} if o[:gzip] require 'zlib' Zlib::GzipWriter.open("#{path}.gz") do |gz| gz.write(content) end end nil end
def compress_asset(content, type)
Compress the given content for the given type by using the
def compress_asset(content, type) case compressor = assets_opts[:"#{type}_compressor"] when :none return content when nil # default, try different compressors else # Allow calling private compress methods return send("compress_#{type}_#{compressor}", content) end compressors = if type == :js [:yui, :closure, :uglifier, :minjs] else [:yui] end compressors.each do |comp| begin # Allow calling private compress methods if c = send("compress_#{type}_#{comp}", content) return c end rescue LoadError, CompressorNotFound end end content end
def compress_css_yui(content)
def compress_css_yui(content) compress_yui(content, :compress_css) end
def compress_js_closure(content)
def compress_js_closure(content) require 'closure-compiler' begin ::Closure::Compiler.new.compile(content) rescue ::Closure::Error => e raise CompressorNotFound, "#{e.class}: #{e.message}", e.backtrace end end
def compress_js_minjs(content)
def compress_js_minjs(content) require 'minjs' Minjs::Compressor::Compressor.new(:debug => false).compress(content).to_js end
def compress_js_uglifier(content)
def compress_js_uglifier(content) begin require 'uglifier' rescue => e # :nocov: raise CompressorNotFound, "#{e.class}: #{e.message}", e.backtrace # :nocov: end Uglifier.compile(content) end
def compress_js_yui(content)
def compress_js_yui(content) compress_yui(content, :compress_js) end
def compress_yui(content, meth)
def compress_yui(content, meth) require 'yuicompressor' ::YUICompressor.public_send(meth, content, :munge => true) rescue ::Errno::ENOENT => e raise CompressorNotFound, "#{e.class}: #{e.message}", e.backtrace end