Skip to content

Commit

Permalink
Local and remote import processing, with tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
joseph committed Aug 19, 2014
1 parent e7d5e05 commit 7f14016
Show file tree
Hide file tree
Showing 6 changed files with 272 additions and 39 deletions.
8 changes: 8 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,23 @@ PATH
GEM
remote: https://rubygems.org/
specs:
addressable (2.3.6)
commonjs (0.2.7)
crack (0.4.2)
safe_yaml (~> 1.0.0)
libv8 (3.16.14.3)
ref (1.0.5)
safe_yaml (1.0.3)
therubyracer (0.12.1)
libv8 (~> 3.16.14.0)
ref
webmock (1.18.0)
addressable (>= 2.3.6)
crack (>= 0.3.2)

PLATFORMS
ruby

DEPENDENCIES
ruby-clean-css!
webmock
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ options](https://github.com/GoalSmashers/clean-css#how-to-use-clean-css-programm
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.
- `process_import` - By default, stylesheets included via `@import` are fetched
and minified inline. Set to false to retain `@import` lines unmodified.
- `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,
Expand All @@ -80,7 +82,6 @@ options](https://github.com/GoalSmashers/clean-css#how-to-use-clean-css-programm

The following options are not yet supported by this library:

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

Expand All @@ -92,6 +93,13 @@ In keeping with the Node library's interface, there are some synonyms available:
`1` means `:first` and `0` means `:none`.


## Contributing

Pull requests are welcome. Please supply a test case with your PR. You
typically run tests like this:

bundle exec ruby test/test_compressor.rb

## License

Ruby-Clean-CSS is released under the [MIT
Expand Down
19 changes: 10 additions & 9 deletions lib/ruby-clean-css/compressor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@ def initialize(options = {})


def compress(stream_or_string)
@last_result = result = { :min => nil }
begin
out = minifier.minify(stream_or_string.to_s)
minifier.minify(stream_or_string.to_s, lambda { |this, errs, data|
result[:min] = data
})
rescue => e
raise(e)
ensure
@last_result = {
:min => out,
:errors => minifier.context.errors,
:warnings => minifier.context.warnings
}
result[:errors] = minifier.context.errors
result[:warnings] = minifier.context.warnings
GC.start # This prevents unexplained segmentation faults in the ref gem!
end
out
result[:min]
end


Expand Down Expand Up @@ -55,8 +56,8 @@ def js_env
@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.native('http', RubyCleanCSS::Exports::Http.new)
@js_env.native('https', RubyCleanCSS::Exports::Http.new)
@js_env
end
end
Expand Down
178 changes: 149 additions & 29 deletions lib/ruby-clean-css/exports.rb
Original file line number Diff line number Diff line change
@@ -1,100 +1,124 @@
# Attribution: much of this stubby code is drawn from
# Attribution: much of this stubbly code is drawn from
# https://github.com/cowboyd/less.rb/blob/master/lib/less/loader.rb
#
# Thanks!
#


require 'pathname'
require 'net/http'
require 'pathname'
require 'uri'

module RubyCleanCSS::Exports

class Process # :nodoc:

def nextTick
lambda { |global, fn|
fn.call
}
lambda { |global, fn| fn.call }
end


def cwd
lambda { Dir.pwd }
end


def exit(*args)
warn("JS process.exit(#{args.first}) called from: \n#{caller.join("\n")}")
end

end



class Console # :nodoc:

def log(*msgs)
puts msgs.join(', ')
STDOUT.puts(msgs.join(', '))
end


def warn(*msgs)
$stderr.puts msgs.join(', ')
STDERR.puts(msgs.join(', '))
end

end



module Path # :nodoc:

def self.join(*components)
# node.js expands path on join
File.expand_path(File.join(*components))
end


def self.dirname(path)
File.dirname(path)
end

def self.basename(path)
File.basename(path)
end

def self.extname(path)
File.extname(path)
def self.resolve(path)
File.expand_path(path)
end

def self.resolve(path)
File.basename(path)

def self.relative(base, path)
Pathname.new(path).relative_path_from(Pathname.new(base)).to_s
end

end



module Util # :nodoc:

def self.error(*errors)
raise errors.join(' ')
end


def self.puts(*args)
args.each { |arg| STDOUT.puts(arg) }
end

end



module FS # :nodoc:

def self.statSync(path)
File.stat(path)
out = File.stat(path)
if out.respond_to?(:define_singleton_method)
out.define_singleton_method(:isFile) { lambda { File.file?(path) } }
else
out.instance_variable_set(:@isFile, File.file?(path))
def out.isFile; lambda { @isFile }; end
end
out
end


def self.existsSync(path)
File.exists?(path)
end


def self.readFile(path, encoding, callback)
callback.call(nil, File.read(path))
end


def self.readFileSync(path, encoding = nil)
buf = Buffer.new(File.read(path), encoding)
encoding.nil? ? buf : buf.toString(encoding)
IO.read(path)
end

end



class Buffer # :nodoc:

def isBuffer(data)
Expand All @@ -104,35 +128,131 @@ def isBuffer(data)
end



module Url # :nodoc:

def self.resolve(*args)
URI.join(*args)
end


def self.parse(url_string)
u = URI.parse(url_string)
result = {}
result['protocol'] = u.scheme + ':' if u.scheme
result['hostname'] = u.host if u.host
result['pathname'] = u.path if u.path
result['port'] = u.port if u.port
result['query'] = u.query if u.query
result['search'] = '?' + u.query if u.query
result['hash'] = '#' + u.fragment if u.fragment
result['protocol'] = u.scheme+':' if u.scheme
result['hostname'] = u.host if u.host
result['pathname'] = u.path if u.path
result['port'] = u.port if u.port
result['query'] = u.query if u.query
result['search'] = '?'+u.query if u.query
result['hash'] = '#'+u.fragment if u.fragment
result
end

end


module Http # :nodoc:
# TODO! Implement #get
end

class Http # :nodoc:

attr_reader :get

def initialize
@get = lambda { |global, options, callback|
err = nil
uri_hash = {}
uri_hash[:host] = options['hostname'] || options['host']
path = options['path'] || options['pathname'] || ''
# We do this because node expects path and query to be combined:
path_components = path.split('?', 2)
if path_components.length > 1
uri_hash[:path] = path_components[0]
uri_hash[:query] = path_components[0]
else
uri_hash[:path] = path_components[0]
end
uri_hash[:port] = options['port'] ? options['port'] : Net::HTTP.http_default_port
# We check this way because of node's http.get:
uri_hash[:scheme] = uri_hash[:port] == Net::HTTP.https_default_port ? 'https' : 'http'
case uri_hash[:scheme]
when 'http'
uri = URI::HTTP.build(uri_hash)
when 'https'
uri = URI::HTTPS.build(uri_hash)
else
raise(Exception, 'import only supports http and https')
end
http = Net::HTTP.new(uri.host, uri.port)
if uri.scheme == 'https'
# Hurrah for insecurity
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.use_ssl = true
end
response = nil
http.start { |req| response = req.get(uri.to_s) }
begin
callback.call(
ServerResponse.new(response.read_body, response.code.to_i)
)
rescue => e
err = e
end
HttpGetResult.new(err);
}
end



class HttpGetResult

attr_accessor :err


def initialize(err)
@err = err
end


def on(event, callback)
if event == 'error' && @err
callback.call(@err)
end
self
end


def setTimeout(timer, callback)
# TODO?
end

end



class ServerResponse

attr_accessor :statusCode
attr_accessor :data # faked because ServerResponse actually implements WriteableStream


def initialize(data, status_code)
@data = data
@statusCode = status_code
end


def on(event, callback)
case event
when 'data'
callback.call(@data)
else
callback.call()
end
self
end

end

module Https # :nodoc:
# TODO! Implement #get
end

end
12 changes: 12 additions & 0 deletions ruby-clean-css.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,16 @@ Gem::Specification.new do |gem|
gem.version = RubyCleanCSS::VERSION
gem.add_dependency('therubyracer')
gem.add_dependency('commonjs')
gem.add_development_dependency('webmock')

# Append all submodule files to the list of gem files.
gem_dir = File.expand_path(File.dirname(__FILE__)) + "/"
`git submodule --quiet foreach pwd`.split($\).each { |submodule_path|
Dir.chdir(submodule_path) {
submodule_relative_path = submodule_path.sub gem_dir, ""
`git ls-files`.split($\).each { |filename|
gem.files << "#{submodule_relative_path}/#{filename}"
}
}
}
end
Loading

0 comments on commit 7f14016

Please sign in to comment.