Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rgrove committed Mar 22, 2008
0 parents commit 0fe0278
Show file tree
Hide file tree
Showing 6 changed files with 4,455 additions and 0 deletions.
5 changes: 5 additions & 0 deletions HISTORY
@@ -0,0 +1,5 @@
CSSMin History
================================================================================

Version 1.0.0 (2008-03-22)
* First release.
62 changes: 62 additions & 0 deletions Rakefile.rb
@@ -0,0 +1,62 @@
#--
# Copyright (c) 2008 Ryan Grove <ryan@wonko.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of this project nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#++

require 'rubygems'
require 'rake/gempackagetask'
require 'rake/rdoctask'

thoth_gemspec = Gem::Specification.new do |s|
s.rubyforge_project = 'riposte'

s.name = 'jsmin'
s.version = '1.0.0'
s.author = 'Ryan Grove'
s.email = 'ryan@wonko.com'
s.homepage = 'http://github.com/rgrove/jsmin/'
s.platform = Gem::Platform::RUBY
s.summary = "Ruby implementation of Douglas Crockford's JSMin JavaScript " +
"minifier."

s.files = FileList['{lib}/**/*', 'HISTORY'].to_a
s.require_path = 'lib'
s.has_rdoc = true

s.required_ruby_version = '>= 1.8.6'
end

Rake::GemPackageTask.new(thoth_gemspec) do |p|
p.need_tar_gz = true
end

Rake::RDocTask.new do |rd|
rd.main = 'JSMin'
rd.title = 'JSMin'
rd.rdoc_dir = 'doc'

rd.rdoc_files.include('lib/**/*.rb')
end
233 changes: 233 additions & 0 deletions lib/jsmin.rb
@@ -0,0 +1,233 @@
#--
# jsmin.rb - Ruby implementation of Douglas Crockford's JSMin.
#
# This is a port of jsmin.c, and is distributed under the same terms, which are
# 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
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#++

require 'strscan'

# = JSMin
#
# Ruby implementation of Douglas Crockford's JavaScript minifier, JSMin.
#
# Author:: Ryan Grove (mailto:ryan@wonko.com)
# Version:: 1.0.0 (2008-03-22)
# Copyright:: Copyright (c) 2008 Ryan Grove. All rights reserved.
# Website:: http://github.com/rgrove/jsmin/
#
# == Example
#
# require 'rubygems'
# require 'jsmin'
#
# File.open('example.js', 'r') {|file| puts JSMin.minify(file) }
#
module JSMin
ORD_LF = "\n"[0].freeze
ORD_SPACE = ' '[0].freeze

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)
@js = StringScanner.new(input.is_a?(IO) ? input.read : input.to_s)

@a = "\n"
@b = nil
@lookahead = nil
@output = ''

action_get

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

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

else
if @b == ' '
if alphanum?(@a)
action_output
else
action_get
end
elsif @b == "\n"
if @a =~ /[}\]\)\\"+-]/
action_output
else
if alphanum?(@a)
action_output
else
action_get
end
end
else
action_output
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 == '"'
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 == '\\'
@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 =~ /[\(,=:\[!&|?{};]/)
@output << @a
@output << @b

loop do
@a = get

if @a == '/'
break
elsif @a == '\\'
@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)
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 ' '
end

# Gets the next character, excluding comments.
def nextchar
c = get
return c unless c == '/'

case peek
when '/'
loop do
c = get
return c if c[0] <= ORD_LF
end

when '*'
get
loop do
case get
when '*'
if peek == '/'
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
end
end
end

0 comments on commit 0fe0278

Please sign in to comment.