Module: SourceMap::JSMin

Defined in:
lib/source_map/jsmin.rb

Overview

JSMin

Ruby implementation of Douglas Crockford’s JavaScript minifier, JSMin.

Author

Ryan Grove ([email protected])

Version

1.0.1 (2008-11-10)

Copyright

Copyright © 2008 Ryan Grove. All rights reserved.

Website

github.com/rgrove/jsmin

Example

require 'rubygems'
require 'jsmin'

File.open('example.js', 'r') {|file| puts JSMin.minify(file) }

Defined Under Namespace

Classes: ParseError

Constant Summary collapse

CHR_APOS =
"'".freeze
CHR_ASTERISK =
'*'.freeze
CHR_BACKSLASH =
'\\'.freeze
CHR_CR =
"\r".freeze
CHR_FRONTSLASH =
'/'.freeze
CHR_LF =
"\n".freeze
CHR_QUOTE =
'"'.freeze
CHR_SPACE =
' '.freeze
ORD_LF =
?\n
ORD_SPACE =
?\
ORD_TILDE =
?~

Class Method Summary collapse

Class Method Details

.minify(input, opts = {}) ⇒ Object

Reads JavaScript from input (which can be a String or an IO object) and returns a String containing minified JS.

opts can contain :input_filename # an input filename to include in the sourcemap (required). :output_filename # an output filename to include in the sourcemap. :source_root # the sourceRoot to include in the sourcemap.

While the output_filename can be anything you like, in order for the source map to work correctly, the :source_root + :input_filename must map to a browser- accessible version of the input file.

If you set an absolute url as :input_filename, then you don’t need to set :source_root, but it’s nicer if you separate those concerns.

Once you have a source map object you’ll probably want to save it into files as in the example:

map = JSMin::SourceMap.minify(File.read("foo.js"),
                 :input_filename => 'foo.js',
                 :output_filename => 'foo.min.js',
                 :source_root => 'http://localhost:3000/javascripts/')

# output the generated, minified, javascript to foo.js.min
File.open('foo.min.js', 'w') { |f| f << map.generated_output }

# output the generated source map to foo.
File.open('foo.map.json', 'w') { |f| f << map.to_s }

Returns:

  • SourceMap



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/source_map/jsmin.rb', line 111

def minify(input, opts={})
  @js = StringScanner.new(input.is_a?(IO) ? input.read : input.to_s)
  @source = input.is_a?(IO) ? input.inspect : input.to_s[0..100]
  @line = 1
  @column = 0
  @file = opts[:input_filename] or raise ":input_filename is required"

  @a         = "\n"
  @b         = nil
  @lookahead = nil
  @source_map = SourceMap.new(:file => opts[:output_filename],
                             :source_root => opts[:source_root],
                             :generated_output => '')

  action_get

  while !@a.nil? do
    case @a
    when CHR_SPACE
      if alphanum?(@b)
        action_output
      else
        action_copy
      end

    when CHR_LF
      if @b == CHR_SPACE
        action_get
      elsif @b =~ /[{\[\(+-]/
        action_output
      else
        if alphanum?(@b)
          action_output
        else
          action_copy
        end
      end

    else
      if @b == CHR_SPACE
        if alphanum?(@a)
          action_output
        else
          action_get
        end
      elsif @b == CHR_LF
        if @a =~ /[}\]\)\\"+-]/
          action_output
        else
          if alphanum?(@a)
            action_output
          else
            action_get
          end
        end
      else
        action_output
      end
    end
  end

  @source_map
end

.raise(err) ⇒ Object



76
77
78
# File 'lib/source_map/jsmin.rb', line 76

def raise(err)
  super ParseError.new(err, @source, @line)
end