module Roda::RodaPlugins::Assets::ClassMethods

def _compile_assets(type)

all asset groups under the given 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 asset_digest(content)

want to use a unique value.
a different digest type or to return a static string if you don't
SHA1 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)
  klass = if algo = assets_opts[:sri]
    require 'digest/sha2'
    ::Digest.const_get(algo.to_s.upcase)
  else
    require 'digest/sha1'
    ::Digest::SHA1
  end
  klass.hexdigest(content)
end

def assets_opts

Return the assets options for this class.
def assets_opts
  opts[:assets]
end

def compile_assets(type=nil)

compile assets for the given asset group.
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 => {})
  end
  if type == nil
    _compile_assets(:css)
    _compile_assets(:js)
  else
    _compile_assets(type)
  end
  if assets_opts[:precompiled]
    require 'json'
    ::FileUtils.mkdir_p(File.dirname(assets_opts[:precompiled]))
    ::File.open(assets_opts[:precompiled], 'wb'){|f| f.write(assets_opts[:compiled].to_json)}
  end
  assets_opts[:compiled]
end

def compile_assets_files(files, type, dirs)

are files in an asset group.
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
  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)

to use a different compressor.
a java runtime. This method can be overridden by the application
but handle cases where yuicompressor isn't installed or can't find
Compress the given content for the given type using yuicompressor,
def compress_asset(content, type)
  case compressor = assets_opts[:"#{type}_compressor"]
  when :none
    return content
  when nil
    # default, try different compressors
  else
    return send("compress_#{type}_#{compressor}", content)
  end
  compressors = if type == :js
    [:yui, :closure, :uglifier, :minjs]
  else
    [:yui]
  end
  compressors.each do |comp|
    begin
      if c = send("compress_#{type}_#{comp}", content)
        return c
      end
    rescue LoadError, CompressorNotFound
    end
  end
  content
end

def compress_css_yui(content)

Compress the CSS using YUI Compressor, requires java runtime
def compress_css_yui(content)
  compress_yui(content, :compress_css)
end

def compress_js_closure(content)

Compress the JS using Google Closure Compiler, requires java runtime
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)

Compress the JS using MinJS, a pure ruby compressor
def compress_js_minjs(content)
  require 'minjs'
  Minjs::Compressor::Compressor.new(:debug => false).compress(content).to_js
end

def compress_js_uglifier(content)

Compress the JS using Uglifier, requires javascript runtime
def compress_js_uglifier(content)
  require 'uglifier'
  Uglifier.compile(content)
end

def compress_js_yui(content)

Compress the CSS using YUI Compressor, requires java runtime
def compress_js_yui(content)
  compress_yui(content, :compress_js)
end

def compress_yui(content, meth)

Compress the CSS/JS using YUI Compressor, requires java runtime
def compress_yui(content, meth)
  require 'yuicompressor'
  ::YUICompressor.send(meth, content, :munge => true)
rescue ::Errno::ENOENT => e
  raise CompressorNotFound, "#{e.class}: #{e.message}", e.backtrace
end