sphere 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.markdown +84 -0
- data/Rakefile +26 -0
- data/VERSION +1 -0
- data/lib/sphere.rb +32 -0
- data/lib/sphere/backends/base.rb +44 -0
- data/lib/sphere/backends/closure.rb +29 -0
- data/lib/sphere/backends/yui.rb +28 -0
- data/lib/sphere/config.rb +55 -0
- data/lib/sphere/css_minifier.rb +29 -0
- data/lib/sphere/helper.rb +38 -0
- data/lib/sphere/package/base.rb +87 -0
- data/lib/sphere/package/javascript.rb +17 -0
- data/lib/sphere/package/stylesheet.rb +17 -0
- data/lib/sphere/packager.rb +48 -0
- data/lib/sphere/tasks/commit.rake +22 -0
- data/lib/sphere/tasks/compass.rake +19 -0
- data/lib/sphere/tasks/sphere.rake +31 -0
- data/lib/sphere/tasks/upload.rake +37 -0
- data/rails/init.rb +2 -0
- data/spec/scenario/config/boot.rb +110 -0
- data/spec/scenario/config/database.yml +0 -0
- data/spec/scenario/config/environment.rb +5 -0
- data/spec/scenario/config/sphere.yml +16 -0
- data/spec/scenario/public/javascripts/custom/file_a.js +9 -0
- data/spec/scenario/public/javascripts/custom/file_b.js +8 -0
- data/spec/scenario/public/javascripts/custom/ignore.js +8 -0
- data/spec/scenario/public/javascripts/file.js +8 -0
- data/spec/scenario/public/stylesheets/compiled/custom.css +1 -0
- data/spec/scenario/public/stylesheets/compiled/print.css +40 -0
- data/spec/spec_helper.rb +50 -0
- data/spec/sphere/config_spec.rb +27 -0
- data/spec/sphere/css_minifier_spec.rb +16 -0
- data/spec/sphere/helper_spec.rb +57 -0
- data/spec/sphere/package/base_spec.rb +46 -0
- data/spec/sphere/package/javascript_spec.rb +19 -0
- data/spec/sphere/package/stylesheet_spec.rb +19 -0
- data/spec/sphere/packager_spec.rb +44 -0
- data/spec/sphere_spec.rb +16 -0
- data/sphere.gemspec +90 -0
- metadata +112 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
module Sphere
|
2
|
+
class Packager
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
def compile(type, options = {})
|
6
|
+
packages(type).values.each do |package|
|
7
|
+
package.compile(options)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def out_of_date?(type = :all)
|
12
|
+
case type
|
13
|
+
when :js, :css
|
14
|
+
packages(type).values.any?(&:out_of_date?)
|
15
|
+
else
|
16
|
+
out_of_date?(:js) || out_of_date?(:css)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def packages(type)
|
21
|
+
case type
|
22
|
+
when :js
|
23
|
+
javascripts
|
24
|
+
when :css
|
25
|
+
stylesheets
|
26
|
+
else
|
27
|
+
raise "Invalid package type: #{type.inspect}."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def javascripts
|
34
|
+
@javascripts ||= Sphere.config.javascripts.map do |target, sources|
|
35
|
+
Package::Javascript.new(target, sources)
|
36
|
+
end.index_by(&:name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def stylesheets
|
40
|
+
@stylesheets ||= Sphere.config.stylesheets.map do |target, sources|
|
41
|
+
Package::Stylesheet.new(target, sources)
|
42
|
+
end.index_by(&:name)
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
namespace :sphere do
|
2
|
+
namespace :commit do
|
3
|
+
|
4
|
+
desc "Commit hook, prevents commits if assets are out fo date"
|
5
|
+
task :hook => 'sphere:base' do
|
6
|
+
out_of_date = Sphere.packager.out_of_date?
|
7
|
+
|
8
|
+
if !out_of_date && Rake::Task.task_defined?("sphere:compass:base")
|
9
|
+
Rake::Task["sphere:compass:base"].invoke
|
10
|
+
project = Compass::Commands::UpdateProject.new(Sphere.config.root.to_s, :quiet => true, :force => false)
|
11
|
+
out_of_date = !!project.new_compiler_instance.out_of_date?
|
12
|
+
end
|
13
|
+
|
14
|
+
if out_of_date
|
15
|
+
puts "\e[31m ** Asset files are out-of-date. **\e[0m"
|
16
|
+
Rake::Task['sphere:compile'].invoke
|
17
|
+
exit(1)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
namespace :sphere do
|
2
|
+
namespace :compass do
|
3
|
+
|
4
|
+
task :base => 'sphere:base' do
|
5
|
+
require 'compass'
|
6
|
+
require 'compass/exec'
|
7
|
+
Compass.add_project_configuration(Sphere.config.root.join("config", "compass.config"))
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Compile compass assets"
|
11
|
+
task :compile => 'sphere:compass:base' do
|
12
|
+
project = Compass::Commands::UpdateProject.new(Sphere.config.root.to_s, :quiet => false, :force => false)
|
13
|
+
project.perform
|
14
|
+
end
|
15
|
+
|
16
|
+
Rake::Task['sphere:compile:css'].enhance(['sphere:compass:compile'])
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
namespace :sphere do
|
2
|
+
|
3
|
+
task :base do
|
4
|
+
require 'sphere'
|
5
|
+
|
6
|
+
Sphere.config.update! do |c|
|
7
|
+
c.env = ENV['SPHERE_ENV'] if ENV['SPHERE_ENV']
|
8
|
+
c.root = ENV['SPHERE_ROOT'] if ENV['SPHERE_ROOT']
|
9
|
+
end
|
10
|
+
|
11
|
+
Rake::Task["sphere:custom"].invoke if Rake::Task.task_defined?("sphere:custom")
|
12
|
+
end
|
13
|
+
|
14
|
+
namespace :compile do
|
15
|
+
|
16
|
+
desc "Compile & package Javascript files"
|
17
|
+
task :js => 'sphere:base' do
|
18
|
+
Sphere.packager.compile(:js, :verbose => true, :force => false)
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Compile & package Stylesheet files"
|
22
|
+
task :css => 'sphere:base' do
|
23
|
+
Sphere.packager.compile(:css, :verbose => true, :force => false)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Compile & package all asset files"
|
29
|
+
task :compile => ['sphere:compile:js', 'sphere:compile:css']
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
namespace :sphere do
|
2
|
+
|
3
|
+
desc "Upload assets to AWS/S3"
|
4
|
+
task :upload => 'sphere:base' do
|
5
|
+
require 'aws/s3'
|
6
|
+
|
7
|
+
config = YAML.load_file(Sphere.config.root.join('config', 's3.yml'))[Sphere.config.env].symbolize_keys
|
8
|
+
bucket = config.delete(:bucket)
|
9
|
+
|
10
|
+
AWS::S3::Base.establish_connection!(config)
|
11
|
+
Dir[Sphere.config.asset_path.join('**', '*')].sort.each do |source|
|
12
|
+
source = Pathname.new(source)
|
13
|
+
local = source.to_s.sub(/^#{Regexp.escape(Sphere.config.public_path)}\//, '')
|
14
|
+
|
15
|
+
if source.directory?
|
16
|
+
puts " ignoring #{local}"
|
17
|
+
next
|
18
|
+
end
|
19
|
+
|
20
|
+
target = source.to_s.sub(/^#{Regexp.escape(Sphere.config.asset_path)}\//, '')
|
21
|
+
etag = Digest::MD5.hexdigest(source.read)
|
22
|
+
|
23
|
+
meta = AWS::S3::S3Object.about(target, bucket) rescue { "last-modified" => '01/01/1970' }
|
24
|
+
if meta['etag'] != etag && Time.parse(meta["last-modified"]) < source.mtime
|
25
|
+
puts "\e[32m S3/store #{local}\e[0m"
|
26
|
+
AWS::S3::S3Object.store(target, source.open, bucket, :access => :public_read)
|
27
|
+
else
|
28
|
+
puts " S3/skip #{local}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Compile and deploy assets to AWS/S3"
|
35
|
+
task :deploy => ['sphere:compile', 'sphere:upload']
|
36
|
+
|
37
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
# Don't change this file!
|
2
|
+
# Configure your app in config/environment.rb and config/environments/*.rb
|
3
|
+
|
4
|
+
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
|
5
|
+
|
6
|
+
module Rails
|
7
|
+
class << self
|
8
|
+
def boot!
|
9
|
+
unless booted?
|
10
|
+
preinitialize
|
11
|
+
pick_boot.run
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def booted?
|
16
|
+
defined? Rails::Initializer
|
17
|
+
end
|
18
|
+
|
19
|
+
def pick_boot
|
20
|
+
(vendor_rails? ? VendorBoot : GemBoot).new
|
21
|
+
end
|
22
|
+
|
23
|
+
def vendor_rails?
|
24
|
+
File.exist?("#{RAILS_ROOT}/vendor/rails")
|
25
|
+
end
|
26
|
+
|
27
|
+
def preinitialize
|
28
|
+
load(preinitializer_path) if File.exist?(preinitializer_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
def preinitializer_path
|
32
|
+
"#{RAILS_ROOT}/config/preinitializer.rb"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Boot
|
37
|
+
def run
|
38
|
+
load_initializer
|
39
|
+
Rails::Initializer.run(:set_load_path)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class VendorBoot < Boot
|
44
|
+
def load_initializer
|
45
|
+
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
|
46
|
+
Rails::Initializer.run(:install_gem_spec_stubs)
|
47
|
+
Rails::GemDependency.add_frozen_gem_path
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class GemBoot < Boot
|
52
|
+
def load_initializer
|
53
|
+
self.class.load_rubygems
|
54
|
+
load_rails_gem
|
55
|
+
require 'initializer'
|
56
|
+
end
|
57
|
+
|
58
|
+
def load_rails_gem
|
59
|
+
if version = self.class.gem_version
|
60
|
+
gem 'rails', version
|
61
|
+
else
|
62
|
+
gem 'rails'
|
63
|
+
end
|
64
|
+
rescue Gem::LoadError => load_error
|
65
|
+
$stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
|
66
|
+
exit 1
|
67
|
+
end
|
68
|
+
|
69
|
+
class << self
|
70
|
+
def rubygems_version
|
71
|
+
Gem::RubyGemsVersion rescue nil
|
72
|
+
end
|
73
|
+
|
74
|
+
def gem_version
|
75
|
+
if defined? RAILS_GEM_VERSION
|
76
|
+
RAILS_GEM_VERSION
|
77
|
+
elsif ENV.include?('RAILS_GEM_VERSION')
|
78
|
+
ENV['RAILS_GEM_VERSION']
|
79
|
+
else
|
80
|
+
parse_gem_version(read_environment_rb)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def load_rubygems
|
85
|
+
min_version = '1.3.2'
|
86
|
+
require 'rubygems'
|
87
|
+
unless rubygems_version >= min_version
|
88
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
|
89
|
+
exit 1
|
90
|
+
end
|
91
|
+
|
92
|
+
rescue LoadError
|
93
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
|
94
|
+
exit 1
|
95
|
+
end
|
96
|
+
|
97
|
+
def parse_gem_version(text)
|
98
|
+
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
def read_environment_rb
|
103
|
+
File.read("#{RAILS_ROOT}/config/environment.rb")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# All that for this:
|
110
|
+
Rails.boot!
|
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
javascripts:
|
2
|
+
application:
|
3
|
+
- http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js
|
4
|
+
- http://jquery-ui.googlecode.com/svn/tags/latest/ui/minified/jquery.ui.core.min.js
|
5
|
+
- javascripts/custom/file_*.js
|
6
|
+
- javascripts/*.js
|
7
|
+
mobile:
|
8
|
+
- http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js
|
9
|
+
- javascripts/*.js
|
10
|
+
|
11
|
+
stylesheets:
|
12
|
+
screen:
|
13
|
+
- http://www.blueprintcss.org/blueprint/src/typography.css
|
14
|
+
- stylesheets/compiled/*.css
|
15
|
+
print:
|
16
|
+
- http://www.blueprintcss.org/blueprint/src/print.css
|
@@ -0,0 +1 @@
|
|
1
|
+
h1 { color: #000; }
|
@@ -0,0 +1,40 @@
|
|
1
|
+
/* --------------------------------------------------------------
|
2
|
+
|
3
|
+
print.css
|
4
|
+
* Gives you some sensible styles for printing pages.
|
5
|
+
* See Readme file in this directory for further instructions.
|
6
|
+
|
7
|
+
Some additions you'll want to make, customized to your markup:
|
8
|
+
#header, #footer, #navigation { display:none; }
|
9
|
+
|
10
|
+
-------------------------------------------------------------- */
|
11
|
+
|
12
|
+
body {
|
13
|
+
line-height: 1.5;
|
14
|
+
color:#000;
|
15
|
+
font-size: 10pt;
|
16
|
+
}
|
17
|
+
|
18
|
+
|
19
|
+
/* Layout
|
20
|
+
-------------------------------------------------------------- */
|
21
|
+
|
22
|
+
.container {
|
23
|
+
background: none;
|
24
|
+
}
|
25
|
+
|
26
|
+
hr {
|
27
|
+
background:#ccc;
|
28
|
+
border:none;
|
29
|
+
}
|
30
|
+
div hr {
|
31
|
+
background: #fff;
|
32
|
+
color: #fff;
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
/* Text
|
37
|
+
-------------------------------------------------------------- */
|
38
|
+
|
39
|
+
h1,h2,h3,h4, h5,h6 { font-family: "Helvetica Neue", Arial, "Lucida Grande", sans-serif; }
|
40
|
+
code { font:.9em "Courier New", Monaco, Courier, monospace; }
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
ENV["RAILS_ENV"] ||= 'test'
|
2
|
+
$: << File.join(File.dirname(__FILE__),'..', 'lib')
|
3
|
+
|
4
|
+
require File.join(File.dirname(__FILE__), 'scenario', 'config', 'boot')
|
5
|
+
require 'active_record'
|
6
|
+
require 'action_controller'
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__),'..', 'rails', 'init.rb')
|
9
|
+
require 'spec/autorun'
|
10
|
+
require 'spec/mocks'
|
11
|
+
ActiveRecord::Base.stub(:establish_connection)
|
12
|
+
|
13
|
+
require 'fakeweb'
|
14
|
+
FakeWeb.allow_net_connect = false
|
15
|
+
FakeWeb.register_uri :get, "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", :body => "(function(A,w){function ma(){}})(window);"
|
16
|
+
FakeWeb.register_uri :get, "http://jquery-ui.googlecode.com/svn/tags/latest/ui/minified/jquery.ui.core.min.js", :body => "(function(c){c.ui=c.ui||{}})(jQuery);"
|
17
|
+
FakeWeb.register_uri :get, "http://www.blueprintcss.org/blueprint/src/typography.css", :body => ".container { background: none; }"
|
18
|
+
FakeWeb.register_uri :get, "http://www.blueprintcss.org/blueprint/src/print.css", :body => "a img { border:none; }"
|
19
|
+
FakeWeb.register_uri :post, "http://closure-compiler.appspot.com/compile", :body => "(function(){})(window);(function(a){a.ui=a.ui||{}})(jQuery);(function(a){a.extend({blank:function(b){return!b||!/\S/.test(b)}})})(JQuery)(function(a){a.extend({present:function(b){return b||/\S/.test(b)}})})(JQuery)(function(a){a.extend({square:function(b){return b*b}})})(JQuery);"
|
20
|
+
|
21
|
+
class Spec::Example::ExampleGroup
|
22
|
+
|
23
|
+
def javascripts
|
24
|
+
Sphere.packager.packages(:js)
|
25
|
+
end
|
26
|
+
|
27
|
+
def stylesheets
|
28
|
+
Sphere.packager.packages(:css)
|
29
|
+
end
|
30
|
+
|
31
|
+
def js_files
|
32
|
+
javascripts.values.map(&:file)
|
33
|
+
end
|
34
|
+
|
35
|
+
def css_files
|
36
|
+
stylesheets.values.map(&:file)
|
37
|
+
end
|
38
|
+
|
39
|
+
before do
|
40
|
+
Sphere.reset!
|
41
|
+
end
|
42
|
+
|
43
|
+
after do
|
44
|
+
(js_files + css_files).each do |file|
|
45
|
+
FileUtils.rm file, :force => true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|