sphere 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +1 -0
  2. data/README.markdown +84 -0
  3. data/Rakefile +26 -0
  4. data/VERSION +1 -0
  5. data/lib/sphere.rb +32 -0
  6. data/lib/sphere/backends/base.rb +44 -0
  7. data/lib/sphere/backends/closure.rb +29 -0
  8. data/lib/sphere/backends/yui.rb +28 -0
  9. data/lib/sphere/config.rb +55 -0
  10. data/lib/sphere/css_minifier.rb +29 -0
  11. data/lib/sphere/helper.rb +38 -0
  12. data/lib/sphere/package/base.rb +87 -0
  13. data/lib/sphere/package/javascript.rb +17 -0
  14. data/lib/sphere/package/stylesheet.rb +17 -0
  15. data/lib/sphere/packager.rb +48 -0
  16. data/lib/sphere/tasks/commit.rake +22 -0
  17. data/lib/sphere/tasks/compass.rake +19 -0
  18. data/lib/sphere/tasks/sphere.rake +31 -0
  19. data/lib/sphere/tasks/upload.rake +37 -0
  20. data/rails/init.rb +2 -0
  21. data/spec/scenario/config/boot.rb +110 -0
  22. data/spec/scenario/config/database.yml +0 -0
  23. data/spec/scenario/config/environment.rb +5 -0
  24. data/spec/scenario/config/sphere.yml +16 -0
  25. data/spec/scenario/public/javascripts/custom/file_a.js +9 -0
  26. data/spec/scenario/public/javascripts/custom/file_b.js +8 -0
  27. data/spec/scenario/public/javascripts/custom/ignore.js +8 -0
  28. data/spec/scenario/public/javascripts/file.js +8 -0
  29. data/spec/scenario/public/stylesheets/compiled/custom.css +1 -0
  30. data/spec/scenario/public/stylesheets/compiled/print.css +40 -0
  31. data/spec/spec_helper.rb +50 -0
  32. data/spec/sphere/config_spec.rb +27 -0
  33. data/spec/sphere/css_minifier_spec.rb +16 -0
  34. data/spec/sphere/helper_spec.rb +57 -0
  35. data/spec/sphere/package/base_spec.rb +46 -0
  36. data/spec/sphere/package/javascript_spec.rb +19 -0
  37. data/spec/sphere/package/stylesheet_spec.rb +19 -0
  38. data/spec/sphere/packager_spec.rb +44 -0
  39. data/spec/sphere_spec.rb +16 -0
  40. data/sphere.gemspec +90 -0
  41. metadata +112 -0
@@ -0,0 +1,17 @@
1
+ module Sphere
2
+ module Package
3
+ class Javascript < Base
4
+
5
+ def self.extension
6
+ 'js'
7
+ end
8
+
9
+ protected
10
+
11
+ def compress(content)
12
+ Sphere.config.backend.new(content).compressed
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Sphere
2
+ module Package
3
+ class Stylesheet < Base
4
+
5
+ def self.extension
6
+ 'css'
7
+ end
8
+
9
+ protected
10
+
11
+ def compress(content)
12
+ Sphere::CSSMinifier.new(content).minify!
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -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,2 @@
1
+ require 'sphere'
2
+ ::ActionView::Base.send(:include, Sphere::Helper)
@@ -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,5 @@
1
+ require File.join(File.dirname(__FILE__), 'boot')
2
+
3
+ Rails::Initializer.run do |config|
4
+ config.action_controller.session = { :key => "_myapp_session", :secret => "492830917060728f9881e1c8efc6cb09492830917060728f9881e1c8efc6cb09" }
5
+ end
@@ -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,9 @@
1
+ // Random JS content
2
+ (function($) {
3
+ $.extend({
4
+ blank: function( text ) {
5
+ return !text || !/\S/.test(text);
6
+ }
7
+ });
8
+ })(JQuery)
9
+
@@ -0,0 +1,8 @@
1
+ // Random JS content
2
+ (function($) {
3
+ $.extend({
4
+ present: function( text ) {
5
+ return text || /\S/.test(text);
6
+ }
7
+ });
8
+ })(JQuery)
@@ -0,0 +1,8 @@
1
+ // Random JS content
2
+ (function($) {
3
+ $.extend({
4
+ buggy: function( text ) {
5
+ // TODO
6
+ }
7
+ });
8
+ })(JQuery)
@@ -0,0 +1,8 @@
1
+ // Random JS content
2
+ (function($) {
3
+ $.extend({
4
+ square: function( num ) {
5
+ return num * num;
6
+ }
7
+ });
8
+ })(JQuery)
@@ -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; }
@@ -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
+