Cory O'Daniel – These are just words Software development, thoughts, and randomness

10Feb/100

A Rails rake file for compressing your Javascript with YUI

Here is a quick rake file I threw together to use with my Ruby YUI 2.0 (I-refuse-to-make-a-gem-
edition).

This of course should be used with the Ruby YUI Compressor I posted about the other day.

This script will tar/gzip all of your javascripts just incase something stupid happens. So you have a little safety net.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
require 'fileutils'
require 'pathname'
 
namespace :js do
  desc <<-INFO
Output Compressed JavaScript to STDOUT; 
  COMPRESS=ALL to compress all Javascript files that DONT contain ".min." 
INFO
 
  task :yui => :environment do
    targz()
    if ENV['COMPRESS'] == 'ALL'
      Dir[Rails.root.to_s / :public / :javascripts / '**/*.js'].each do |javascript|
        next if javascript =~ /\.min\./
 
        compress(javascript)
      end
    else
      if File.exist?(Rails.root + "config/yui.yml")
        javascripts = YAML.load(File.open("config/yui.yml").read)["javascripts"]
 
        if !javascripts.blank?
          javascripts.each {|script| compress(Rails.root + "public/javascripts" + script)}
        else
          raise Exception, "No javascript files in config/yui.yml" 
        end
      else
        raise Exception, "config/yui.yml Not Found; Do rake js:generate to create one or COMPRESS=ALL to run without a config file"
      end
    end
  end
 
  desc "Generate YUI Compressor Config file"
  task :generate => :environment do
    config_path = Rails.root + "config/yui.yml"
    File.open(config_path, "w+") do |f|
      f.puts <<-CONFIG
---
javascripts:
  - "application.js"
  - "jquery.js"
CONFIG
      puts config_path
    end
  end
 
  def targz()
    tgz_file = "#{Time.now.to_i}.javascripts.tgz"
    `cd #{Rails.root + "public"}; tar -zcf #{tgz_file} javascripts/`
    puts "Backed up assets to: #{tgz_file}"
  end
 
  def compress(path)
    puts "Compressing #{path}"
    file_handle = File.open(path)
    compressed_output = YUI.compress_safe file_handle
    file_handle.close
 
    #overwrite the file
    File.open(path, "w+") { |file| file.puts compressed_output }
  end
 
end

Wanna use it?
1. Drop it in your lib/tasks folder or wherever your Rakefile looks

You can compress 'everything' or specific files.

If you want to only compress specific Javascript files do:

1
2
3
rake js:generate 
# Edit your config/yui.yml file
rake js:yui

If you want to compress "everything" (It actually won't compress files that contain ".min.". You can remove the regexp's if you don't like it.)

1
rake js:yui COMPRESS=ALL

Yay, now your raking it in (Pun harhar) w/ your web2.0 yui compressed rails app. Woot woot.

Post to Twitter Post to Digg Post to Facebook Post to Reddit Post to StumbleUpon

Tagged as: , , , No Comments
8Feb/101

Cory’s Ruby YUI Compressor v 2.0 Simpler, shorter.

So, a while ago I write a Ruby YUI Compressor Wrapper which is still available and works great (although it could use a newer jar file) as far as I know from Mandula's Blog. Some other guy also wrote one that pretty much had the same functionality as my gem. He must have hated it or something, I dunno. Even another guy wrote a wrapper for Closure Compiler if thats your bag.

Anywho, on a new project I'm working on *I just need a inline YUI compressor* and I dont give a damn about anything else like bundling, globbing or whatever. So I ended up throwing together this little (~50 lines less comments) Ruby YUI Compressor to do my dirty work.

I won't make it a gem probably, because if I do someone will just make a ruby-yui-simpler-also gem and put it on digg and get a bigger following :P (</sarcasm>)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
require 'open3'
require 'stringio'
 
class YUI
  include Open3 
  JAR_PATH = File.join(File.dirname(__FILE__),'yuicompressor-2.4.2.jar')
 
  class << self
    # @param io [String|File]
    # @param options [Hash] - See YUI.cli
    # @returns String
    #
    def compress(io, options = {})
      options[:type]    ||= :js
      options[:charset] ||= "utf-8"
 
      stdin, stdout, stderr = Open3.popen3( YUI.cli(options) )
      stdin.puts streamify(io).read
      stdin.close
 
      my_stderr = stderr.read
      my_stdout = stdout.read
 
      # if compression failed, just output original IO
      if my_stderr.empty?
        return my_stdout
      else
        raise Exception, my_stderr
      end
    end
 
    # If any exceptions are raised, the original string will be
    #   returned incase you are compressing stuff during a deploy
    #   and _just_dont_care_
    def compress_safe(io, options={})
      YUI.compress(io, options)
    rescue Exception => ex
      puts ex.message
      return streamify(io).read      
    end
 
    # Sets up the command line options
    # @param options [Hash]
    #   :jar_path         - [String] Path to the jar file, default "./yuicompress-2.4.2.jar"
    #   :charset          - [String] default 'utf-8'
    #   :type             - [Symbol] Options: js/css, default :js
    #   :line_break       - [Fixnum] Column to add line break at
    #   
    #   if the type of compression is JS, then additional options:
    #     :nomunge        - [Boolean] do not obfuscate
    #     :preserve_semi  - [Boolean] preserve all semicolons
    #     :disable_opt    - [Boolean] Disable all micro optimizations
    # 
    # @returns String
    #
    def cli(options)
      _cmd = ["java -jar #{options[:jar_path] || JAR_PATH}"]
      _cmd << "--type #{options[:type]}"
      _cmd << "--charset #{options[:charset]}" if options[:charset]
      _cmd << "--charset #{options[:line_break]}" if options[:line_break]
 
      if options[:type] == :js  
        _cmd << "--nomunge" if options[:nomunge]
        _cmd << "--preserve-semi" if options[:preserve_semi]
        _cmd << "--disable-optimizations" if options[:disable_opt]
      end
 
      _cmd.join(' ') 
    end
 
    # If a file or a string, treat it like its a stream
    #
    # @param string_or_stream [File|String]
    # @return StringIO
    #
    def streamify(string_or_stream)
      if string_or_stream.respond_to?(:read)
        string_or_stream.rewind if string_or_stream.eof?
        string_or_stream
      else
        StringIO.new(string_or_stream)
      end
    end
 
  end #end class << self
 
end

Wanna use it?
1. Copy the code above, throw it in your lib folder or where ever
2. Download the YUI compressor JAR file and put it in the same directory.
3. Do something like the following...

1
2
3
YUI.compress("function weebleep(){var cool_variable= 3; return cool_variable;}") #=> "function weebleep(){var a=3;return a};"
YUI.compress(File.open( "public/javascripts/application.js")) #=> A bunch of compressed javascript
YUI.compress(File.open( "public/stylesheets/application.css"), {:type => :css}) #=> Compressed stylesheet

Other options include:
:jar_path - [String] Path to the jar file, default "./yuicompress-2.4.2.jar"
:charset - [String] default 'utf-8'
:type - [Symbol] Options: js/css, default :js
:line_break - [Fixnum] Column to add line break at

if the type of compression is JS, then additional options:
:nomunge - [Boolean] do not obfuscate
:preserve_semi - [Boolean] preserve all semicolons
:disable_opt - [Boolean] Disable all micro optimizations

Yay have a blast. Its another compression wrapper.

Post to Twitter Post to Digg Post to Facebook Post to Reddit Post to StumbleUpon

Tagged as: , , 1 Comment