Permalink
Browse files

Fix Ruby 1.9 compatibility; minor performance improvements

  • Loading branch information...
1 parent db6b78d commit d524770c3200b71788301bf9779ba8d2903b4cfe @rgrove committed Nov 11, 2008
Showing with 77 additions and 57 deletions.
  1. +5 −1 HISTORY
  2. +1 −1 Rakefile.rb
  3. +71 −55 lib/jsmin.rb
View
@@ -1,5 +1,9 @@
-CSSMin History
+JSMin History
================================================================================
+Version 1.0.1 (2008-11-10)
+ * Ruby 1.9 compatibility.
+ * Minor performance improvements.
+
Version 1.0.0 (2008-03-22)
* First release.
View
@@ -34,7 +34,7 @@
s.rubyforge_project = 'riposte'
s.name = 'jsmin'
- s.version = '1.0.0'
+ s.version = '1.0.1'
s.author = 'Ryan Grove'
s.email = 'ryan@wonko.com'
s.homepage = 'http://github.com/rgrove/jsmin/'
View
@@ -5,19 +5,19 @@
# as follows:
#
# Copyright (c) 2002 Douglas Crockford (www.crockford.com)
-#
+#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
-#
+#
# The Software shall be used for Good, not Evil.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -34,7 +34,7 @@
# Ruby implementation of Douglas Crockford's JavaScript minifier, JSMin.
#
# Author:: Ryan Grove (mailto:ryan@wonko.com)
-# Version:: 1.0.0 (2008-03-22)
+# Version:: 1.0.1 (2008-11-10)
# Copyright:: Copyright (c) 2008 Ryan Grove. All rights reserved.
# Website:: http://github.com/rgrove/jsmin/
#
@@ -46,11 +46,27 @@
# File.open('example.js', 'r') {|file| puts JSMin.minify(file) }
#
module JSMin
- ORD_LF = "\n"[0].freeze
- ORD_SPACE = ' '[0].freeze
-
+ 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
+
+ if RUBY_VERSION >= '1.9'
+ ORD_LF = "\n".freeze
+ ORD_SPACE = ' '.freeze
+ ORD_TILDE = '~'.freeze
+ else
+ ORD_LF = "\n"[0].freeze
+ ORD_SPACE = ' '[0].freeze
+ ORD_TILDE = '~'[0].freeze
+ end
+
class << self
-
+
# Reads JavaScript from +input+ (which can be a String or an IO object) and
# returns a String containing minified JS.
def minify(input)
@@ -60,20 +76,20 @@ def minify(input)
@b = nil
@lookahead = nil
@output = ''
-
+
action_get
-
+
while !@a.nil? do
case @a
- when ' '
+ when CHR_SPACE
if alphanum?(@b)
action_output
else
action_copy
end
-
- when "\n"
- if @b == ' '
+
+ when CHR_LF
+ if @b == CHR_SPACE
action_get
elsif @b =~ /[{\[\(+-]/
action_output
@@ -84,15 +100,15 @@ def minify(input)
action_copy
end
end
-
+
else
- if @b == ' '
+ if @b == CHR_SPACE
if alphanum?(@a)
action_output
else
action_get
end
- elsif @b == "\n"
+ elsif @b == CHR_LF
if @a =~ /[}\]\)\\"+-]/
action_output
else
@@ -107,124 +123,124 @@ def minify(input)
end
end
end
-
+
@output
end
-
+
private
-
+
# Corresponds to action(1) in jsmin.c.
def action_output
@output << @a
action_copy
end
-
+
# Corresponds to action(2) in jsmin.c.
def action_copy
@a = @b
-
- if @a == '\'' || @a == '"'
+
+ if @a == CHR_APOS || @a == CHR_QUOTE
loop do
@output << @a
@a = get
-
+
break if @a == @b
-
+
if @a[0] <= ORD_LF
raise "JSMin parse error: unterminated string literal: #{@a}"
end
-
- if @a == '\\'
+
+ if @a == CHR_BACKSLASH
@output << @a
@a = get
-
+
if @a[0] <= ORD_LF
raise "JSMin parse error: unterminated string literal: #{@a}"
end
end
end
end
-
+
action_get
end
-
+
# Corresponds to action(3) in jsmin.c.
def action_get
@b = nextchar
-
- if @b == '/' && (@a == "\n" || @a =~ /[\(,=:\[!&|?{};]/)
+
+ if @b == CHR_FRONTSLASH && (@a == CHR_LF || @a =~ /[\(,=:\[!&|?{};]/)
@output << @a
@output << @b
-
+
loop do
@a = get
-
- if @a == '/'
+
+ if @a == CHR_FRONTSLASH
break
- elsif @a == '\\'
+ elsif @a == CHR_BACKSLASH
@output << @a
@a = get
elsif @a[0] <= ORD_LF
raise "JSMin parse error: unterminated regular expression " +
"literal: #{@a}"
end
-
+
@output << @a
end
-
+
@b = nextchar
end
end
-
+
# Returns true if +c+ is a letter, digit, underscore, dollar sign,
# backslash, or non-ASCII character.
def alphanum?(c)
- c.is_a?(String) && !c.empty? && (c[0] > 126 || c =~ /[0-9a-z_$\\]/i)
+ c.is_a?(String) && !c.empty? && (c[0] > ORD_TILDE || c =~ /[0-9a-z_$\\]/i)
end
-
+
# Returns the next character from the input. If the character is a control
# character, it will be translated to a space or linefeed.
def get
c = @lookahead.nil? ? @js.getch : @lookahead
@lookahead = nil
- return c if c.nil? || c == "\n" || c[0] >= ORD_SPACE
- return "\n" if c == "\r"
+ return c if c.nil? || c == CHR_LF || c[0] >= ORD_SPACE
+ return "\n" if c == CHR_CR
return ' '
end
-
+
# Gets the next character, excluding comments.
def nextchar
c = get
- return c unless c == '/'
-
+ return c unless c == CHR_FRONTSLASH
+
case peek
- when '/'
+ when CHR_FRONTSLASH
loop do
c = get
return c if c[0] <= ORD_LF
end
-
- when '*'
+
+ when CHR_ASTERISK
get
loop do
case get
- when '*'
- if peek == '/'
+ when CHR_ASTERISK
+ if peek == CHR_FRONTSLASH
get
return ' '
end
-
+
when nil
raise 'JSMin parse error: unterminated comment'
end
end
-
+
else
return c
end
end
-
+
# Gets the next character without getting it.
def peek
@lookahead = get

0 comments on commit d524770

Please sign in to comment.