Allow Jammit to be extended to package and compress other types of assests #229

wants to merge 3 commits into from

4 participants


I use Jammit on a production level service and am happy with it, however I came across a need to be able to package and compress other static assets that are not stylesheets, javascripts, or JSTs.

In order to do this, the attached changes are needed to be able to allow me to extend Jammit with custom asset types. It is important to me to keep using Jammit, and I would greatly appreciate this functionality being merged into the main repo, and I'm open to any changes you feel are needed to get this in.

Below is a modified version of what I am using to interact with the fork of Jammit with these included changes.

module Jammit




  class Compressor
    # no actual compression applied, just formats it correctly, but could support compression
    def compress_json(paths)
      namespace   = JSON_NAMESPACE
      base_path   = find_base_path(paths)
      compiled    = do |path|
        contents  = read_binary_file(path)
        name      = json_name(path, base_path)
        "#{namespace}['#{name}'] = #{JSON_FUNCTION}('#{contents}');"
      setup_namespace = "#{namespace} = #{namespace} || {};"
      [JST_START, setup_namespace, compiled, JST_END].flatten.join("\n")

    def json_name(path, base_path)
      return File.basename(path, ".#{JSON_EXTENSION}") unless base_path
      path.gsub(/\A#{Regexp.escape(base_path)}\/(.*)\.#{JSON_EXTENSION}\Z/, '\1')

  class Packager
    def pack_jsons(package)
      compressor.compress_json(package_for(package, :json)[:paths])

  module Helper
    def include_jsons(*packages)
      options = packages.extract_options!
      html_safe {|pack|
        Jammit.asset_url(pack, :json)
      } {|pack|
        javascript_include_tag pack, options

Please note that this is a initial pass and is very conservative in what it changes, however a couple of more drastic changes could make this functionality more streamlined with the rest of the project.

Ideally, I feel that JSTs should also be broken out ouf the Javascript packaging / compression, and the pipeline of packaging and compressing be made more generic to support handling user defined asset types as a first class citizen. Thus, each type, user defined or included, will flow through a similar work flow.

However, before embarking on this, I would greatly appreciate feedback on what I have so far, how to determine what asset type (JS or CSS) an asset supplied in the assets.yml would be, and if the way user defined templates are created is acceptable.

DocumentCloud member

I'm a bit confused as to why you don't simply include these files as regular JavaScript, not JSON. That's what you're ultimately doing, isn't it?

DocumentCloud member

👍 - This would allow precompiling JSTs as well, a big win for debugging since you could get a file name and line number from template errors. It's currently difficult to alter the behavior of JST compilation since it's tied into javascript compilation.


@jashkenas Thanks for your quick reply.

While you're correct, the example above does basically that (and is actually how we handle this case at present), however, it is more of a proof of concept then what is going to be implemented for JSONs.

JSONs have different attributes then javascripts or JSTs, they need to be stored without javascript inside of them for portability, they don't have any args that are passed to them for rendering, as they are not rendered, they can also "stack" on each other, ie, two JSONs could exist, one of default values and one including overrides of the original, and keeping them in the JST namespace means keeping code to determine if the template is a JST or a JSON in the client side. It would be cleaner to support them as a first class type.


@jashkenas hey! Now, 3 months later, any different feelings about this? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment