paolochiodi / htmlcompressor

A work in progress port of google's htmlcompressor.jar
Other
150 stars 26 forks source link

compressing js templates #18

Closed izelnakri closed 9 years ago

izelnakri commented 9 years ago

Is there a way to compress .jst.eco files with this gem automatically? I've been using the gem happily for .html.erb files but js templates cause HTML whitespace issue for inline-block elements.

paolochiodi commented 9 years ago

@izelnakri What is your workflow? The base class should compress any kind of file, whilst the rack middleware only compress responses whose content-type contains "html". How are you serving those templates?

For whitespace problems, are you using the :remove_intertag_spaces option?

izelnakri commented 9 years ago

yes I'm using the middleware correctly for erb templates. I have my js templates under assets/javascripts/templates directory. Actually what I have in mind is to run a task/process along with "rails s" in development to compress js templates whenever a file changes in the js template directory. Then I can require the compressed versions in the sprockets directives, maybe under "assets/javascripts/templates/compressed" directory. Any ideas how to achieve this in rails?

izelnakri commented 9 years ago

I wrote the following code to implement this feature. It certainly introduces some "conventions" (the templates/compiled directory), but with little refactoring it might be useful for others as well:

P.S puts are just for debugging.

# on 'config/environments/development.rb'
Rails.application.configure do

  #default development settings...

  #code for this feature:
  config.after_initialize do
    def create_compiled_js_template(item)
      unless File.directory?(item) #necessary for the dir.glob at start
        rel_path = item.sub("#{root}/app/assets/javascripts/templates/", "")
        compile_dir = "#{root}/app/assets/javascripts/templates/compiled/#{rel_path}"
        dirname = File.dirname(compile_dir)
        unless File.directory?(dirname) #create the necessary directories before write
          FileUtils.mkdir_p(dirname)
        end
        compressor = HtmlCompressor::Compressor.new(:remove_intertag_spaces => true)
        new_file = compressor.compress(File.read(item))
        IO.write(compile_dir, new_file)
        puts "Template compiled"
      end
    end

    Dir.glob("#{Rails.root}/app/assets/javascripts/templates/**/*") do |item| #this block runs on start
      unless item.scan("compiled")[0] #means its a compiled dir
        create_compiled_js_template(item)
      end
    end

    #CAVEAT: IT DOESN'T DELETE DIRECTORIES + FILES ON START
    #+ DOESN'T DELETE DIR WHILE IT RUNS
    listener = Listen.to("app/assets/javascripts/templates", ignore: %r{^(?: compiled )(/|$)}x) do |modified, added, removed|
      if modified[0]
        puts "MODIFIED - #{modified[0]}"
        create_compiled_js_template(modified[0]) 
      elsif added[0]
        puts "ADDED - #{added[0]}"
        create_compiled_js_template(added[0])
      elsif removed[0]
        puts "DELETED - #{removed[0]}"
        rel_path = removed[0].sub("#{root}/app/assets/javascripts/templates/", "")
        File.delete("#{root}/app/assets/javascripts/templates/compiled/#{rel_path}")
        puts "Compiled template removed"
      end
    end

    listener.start
  end
end
paolochiodi commented 9 years ago

Thank you for sharing your solution. I guess an even better option is to hook into the assets compilation pipeline, but at the moment I'm not looking to include this functionality into the gem.