Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
joseph committed Aug 18, 2014
0 parents commit e7d5e05
Show file tree
Hide file tree
Showing 14 changed files with 526 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "lib/javascript/clean-css"]
path = lib/javascript/clean-css
url = https://github.com/GoalSmashers/clean-css.git
25 changes: 25 additions & 0 deletions EXAMPLE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env ruby

#### If you wanted to create a Ruby script that took raw CSS from STDIN and
#### emitted the minified result to STDOUT, here's how you might do it. (Errors
#### and warnings are sent to STDERR.)

require 'ruby-clean-css'

begin
compressor = RubyCleanCSS::Compressor.new
compressor.compress(ARGV[0] || ARGF.read)
rescue => e
STDERR.puts("FAILED: #{e.inspect}")
STDERR.puts(e.backtrace.join("\n") + "\n")
ensure
out = compressor.last_result
STDERR.puts(out[:errors].join("\n")) if out[:errors].any?
STDERR.puts(out[:warnings].join("\n")) if out[:warnings].any?
STDOUT.puts(out[:min])
end


#### This example itself is runnable. For example, try:
####
#### cat raw.css | ruby EXAMPLE.md > min.css
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source 'https://rubygems.org'

# Specify dependencies in ruby-clean-css.gemspec!
gemspec
22 changes: 22 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
PATH
remote: .
specs:
ruby-clean-css (0.0.1)
commonjs
therubyracer

GEM
remote: https://rubygems.org/
specs:
commonjs (0.2.7)
libv8 (3.16.14.3)
ref (1.0.5)
therubyracer (0.12.1)
libv8 (~> 3.16.14.0)
ref

PLATFORMS
ruby

DEPENDENCIES
ruby-clean-css!
19 changes: 19 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2014 OverDrive, Inc.

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 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.
98 changes: 98 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Ruby-Clean-CSS compressor

This gem provides a Ruby interface to the
[Clean-CSS](https://github.com/GoalSmashers/clean-css) Node library for
minifying CSS files.

Ruby-Clean-CSS provides much more modern and compatible minification of
stylesheets than the old [YUI
compressor](https://github.com/sstephenson/ruby-yui-compressor) (which was
[discontinued](http://www.yuiblog.com/blog/2012/10/16/state-of-yui-compressor)
by Yahoo in 2012).


## Usage

You can use this library with Rails, or with Sprockets in non-Rails projects,
or simply as a standalone library.


### As a plain Ruby library:

Here's the simplest thing that could possibly work:

>> require 'ruby-clean-css'
>> RubyCleanCSS::Compressor.new.compress('a { color: chartreuse; }')
=> "a{color:#7fff00}"


### With Sprockets:

You can register the Compressor as Sprocket's default CSS compressor like this:

require 'ruby-clean-css'
require 'ruby-clean-css/sprockets'
RubyCleanCSS::Sprockets.register(sprockets_env)


### With Rails 3 or Rails 4:

Just add this gem to the `:assets` group of your `Gemfile`. Ruby-Clean-CSS
will automatically become the default compressor for CSS files.

If you prefer, you can make it explicit in `config/environments/production.rb`:

config.assets.css_compressor = :cleancss

Alternatively, if you want to customize the compressor with options,
you can assign an instance of the compressor to that setting:

config.assets.css_compressor = RubyCleanCSS::Compressor.new(
rebase_urls: false,
keep_breaks: true
)


## Options

This library supports the following [Clean-CSS
options](https://github.com/GoalSmashers/clean-css#how-to-use-clean-css-programmatically):

- `keep_special_comments` - A "special comment" is one that begins with `/*!`.
You can keep them all with `:all`, just the first with `:first`, or
remove them all with `:none`. The default is `:all`.
- `keep_breaks` - By default, all linebreaks are stripped. Set to `true` to
retain them.
- `root` - This is the path used to resolve absolute `@import` rules and rebase
relative URLS. A string. Defaults to the present working directory.
- `relative_to` - This path is used to resovle relative `@import` rules and
URLs. A string. No default.
- `rebase_urls` - By default, all URLs are rebased to the root. Set to `false`
to prevent rebasing.
- `advanced` - By default, Clean-CSS applies some advanced optimizations,
like selector and property merging, reduction, etc). Set to `false` to
prevent these optimizations.
- `rounding_precision` - The rounding precision on measurements in your CSS.
An integer, defaulting to `2`.
- `compatibility` - Use this to force Clean-CSS to be compatible with `ie7`
or `ie8`. Default is neither. Supply as a symbol (`:ie7`) or
string (`'ie7'`).

The following options are not yet supported by this library:

- `process_import`
- `benchmark`
- `debug`

In keeping with the Node library's interface, there are some synonyms available:

- `:no_rebase => true` is the same as `:rebase_urls => false`.
- `:no_advanced => true` is the same as `:advanced => false`.
- `:keep_special_comments` has an alternative syntax: `'*'` means `:all`,
`1` means `:first` and `0` means `:none`.


## License

Ruby-Clean-CSS is released under the [MIT
Licence](https://github.com/joseph/ruby-clean-css/blob/master/LICENSE).
1 change: 1 addition & 0 deletions lib/javascript/clean-css
Submodule clean-css added at 14da59
6 changes: 6 additions & 0 deletions lib/ruby-clean-css.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require 'therubyracer'
require 'commonjs'
require 'ruby-clean-css/version'
require 'ruby-clean-css/exports'
require 'ruby-clean-css/compressor'
require 'ruby-clean-css/railtie' if defined?(Rails)
141 changes: 141 additions & 0 deletions lib/ruby-clean-css/compressor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
class RubyCleanCSS::Compressor

LIB_PATH = File.expand_path(File.dirname(__FILE__)+'/../javascript')

attr_reader(:last_result)


def initialize(options = {})
@js_options = js_options_from_hash(options)
end


def compress(stream_or_string)
begin
out = minifier.minify(stream_or_string.to_s)
rescue => e
raise(e)
ensure
@last_result = {
:min => out,
:errors => minifier.context.errors,
:warnings => minifier.context.warnings
}
end
out
end


def minifier
@minifier ||= minifier_class.call(@js_options)
end


protected

def js_runtime
if @js_runtime
@js_runtime
else
@js_runtime = V8::Context.new
@js_runtime['process'] = RubyCleanCSS::Exports::Process.new
@js_runtime['console'] = RubyCleanCSS::Exports::Console.new
@js_runtime['Buffer'] = RubyCleanCSS::Exports::Buffer.new
@js_runtime
end
end


def js_env
if @js_env
@js_env
else
@js_env = CommonJS::Environment.new(js_runtime, :path => LIB_PATH)
@js_env.native('path', RubyCleanCSS::Exports::Path)
@js_env.native('util', RubyCleanCSS::Exports::Util)
@js_env.native('fs', RubyCleanCSS::Exports::FS)
@js_env.native('url', RubyCleanCSS::Exports::Url)
@js_env.native('http', RubyCleanCSS::Exports::Http)
@js_env.native('https', RubyCleanCSS::Exports::Https)
@js_env
end
end


def minifier_class
@minifier_class ||= js_env.require('clean-css/index')
end


# See README.md for a description of each option, and see
# https://github.com/GoalSmashers/clean-css#how-to-use-clean-css-programmatically
# for the JS translation.
#
def js_options_from_hash(options)
js_opts = {}

if options.has_key?(:keep_special_comments)
js_opts['keepSpecialComments'] = {
'all' => '*',
'first' => 1,
'none' => 0,
'*' => '*',
'1' => 1,
'0' => 0
}[options[:keep_special_comments].to_s]
end

if options.has_key?(:keep_breaks)
js_opts['keepBreaks'] = options[:keep_breaks] ? true : false
end

if options.has_key?(:root)
js_opts['root'] = options[:root].to_s
end

if options.has_key?(:relative_to)
js_opts['relativeTo'] = options[:relative_to].to_s
end

if options.has_key?(:no_rebase)
js_opts['noRebase'] = options[:no_rebase] ? true : false
elsif !options[:rebase_urls].nil?
js_opts['noRebase'] = options[:rebase_urls] ? false : true
end

if options.has_key?(:no_advanced)
js_opts['noAdvanced'] = options[:no_advanced] ? true : false
elsif !options[:advanced].nil?
js_opts['noAdvanced'] = options[:advanced] ? false : true
end

if options.has_key?(:rounding_precision)
js_opts['roundingPrecision'] = options[:rounding_precision].to_i
end

if options.has_key?(:compatibility)
js_opts['compatibility'] = options[:compatibility].to_s
unless ['ie7', 'ie8'].include?(js_opts['compatibility'])
raise(
'Ruby-Clean-CSS: unknown compatibility setting: '+
js_opts['compatibility']
)
end
end

if options.has_key?(:process_import)
raise('Ruby-Clean-CSS: processImport option is not yet supported')
end

if options.has_key?(:benchmark)
raise('Ruby-Clean-CSS: benchmark option is not yet supported')
end

if options.has_key?(:debug)
raise('Ruby-Clean-CSS: debug option is not yet supported')
end

js_opts
end

end
Loading

0 comments on commit e7d5e05

Please sign in to comment.