asset-resource 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # AssetResource
2
+
3
+ Serve up your CSS and Javascript as first-class resources.
4
+
5
+ Supports in-line rendering of engines such as Sass and Less. These files will
6
+ be served with 24-hour HTTP cache expiry.
7
+
8
+ Built-in configuration and helpers for Rails 2.x, Rails 3.x and Sinatra.
9
+
10
+ ## Usage
11
+
12
+ ### Rails 2.x
13
+
14
+ # public/stylesheets/*.{css|less|sass}
15
+ # public/javascripts/*.js
16
+
17
+ # config/environment.rb
18
+ config.gem "asset-resource"
19
+
20
+ # app/views/layouts/application.html.erb
21
+ <html>
22
+ <head>
23
+ <%= asset_resource_stylesheets %>
24
+ <%= asset_resource_scripts %>
25
+ </head>
26
+ </html>
27
+
28
+ ### Rails 3.x
29
+
30
+ # public/stylesheets/*.{css|less|sass}
31
+ # public/javascripts/*.js
32
+
33
+ # Gemfile
34
+ gem "asset_resource"
35
+
36
+ # app/views/layouts/application.html.erb
37
+ <html>
38
+ <head>
39
+ <%= asset_resource_stylesheets %>
40
+ <%= asset_resource_scripts %>
41
+ </head>
42
+ </html>
43
+
44
+ ### Sinatra
45
+
46
+ # assets/styles/*.{css|less|sass}
47
+ # assets/scripts/*.js
48
+
49
+ # app.rb
50
+ require "asset_resource"
51
+
52
+ class App < Sinatra::Base
53
+ register Sinatra::AssetResource
54
+ end
55
+
56
+ __END__
57
+
58
+ @@ layout
59
+ %html
60
+ %head
61
+ = asset_resource_scripts
62
+ = asset_resource_styles
63
+
64
+ ## Technical Details
65
+
66
+ `AssetResource::Middleware` serves requests at `/assets/stylesheets.css` and
67
+ `/assets/javascripts.js`.
68
+
69
+ The gem will add appropriate view helpers to your framework of choice.
70
+
71
+ You can use the middleware yourself like this:
72
+
73
+ use AssetResource::Middleware,
74
+ :base_path => "public",
75
+ :handlers => { :javascripts => "text/javascript",
76
+ :stylesheets => "text/css" }
77
+
78
+ ## Copyright
79
+
80
+ MIT License
81
+
82
+ ## Author
83
+
84
+ David Dollar
85
+
86
+ [http://daviddollar.org](http://daviddollar.org)
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ require "rake"
2
+ require "rspec"
3
+ require "rspec/core/rake_task"
4
+
5
+ $:.unshift File.expand_path("../lib", __FILE__)
6
+ require "asset_resource"
7
+
8
+ task :default => :spec
9
+
10
+ desc "Run all specs"
11
+ Rspec::Core::RakeTask.new(:spec) do |t|
12
+ t.pattern = 'spec/**/*_spec.rb'
13
+ end
14
+
15
+ desc "Generate RCov code coverage report"
16
+ task :rcov => "rcov:build" do
17
+ %x{ open coverage/index.html }
18
+ end
19
+
20
+ Rspec::Core::RakeTask.new("rcov:build") do |t|
21
+ t.pattern = 'spec/**/*_spec.rb'
22
+ t.rcov = true
23
+ t.rcov_opts = [ "--exclude", Gem.default_dir , "--exclude", "spec" ]
24
+ end
25
+
26
+ ######################################################
27
+
28
+ begin
29
+ require 'jeweler'
30
+ Jeweler::Tasks.new do |s|
31
+ s.name = "asset-resource"
32
+ s.version = AssetResource::VERSION
33
+
34
+ s.summary = "Manage CSS/JS assets as dynamic resources rather than static files"
35
+ s.description = s.summary
36
+ s.author = "David Dollar"
37
+ s.email = "ddollar@gmail.com"
38
+ s.homepage = "http://github.com/ddollar/asset-resource"
39
+
40
+ s.platform = Gem::Platform::RUBY
41
+ s.has_rdoc = false
42
+
43
+ s.files = %w(Rakefile README.md) + Dir["{bin,lib}/**/*"]
44
+ s.require_path = "lib"
45
+
46
+ s.add_development_dependency 'artifice', '~> 0.5'
47
+ s.add_development_dependency 'fakefs', '~> 0.2.1'
48
+ s.add_development_dependency 'haml', '~> 3.0.9'
49
+ s.add_development_dependency 'less', '~> 1.2.21'
50
+ s.add_development_dependency 'rake', '~> 0.8.7'
51
+ s.add_development_dependency 'rest-client', '~> 1.5.1'
52
+ s.add_development_dependency 'rcov', '~> 0.9.8'
53
+ s.add_development_dependency 'rspec', '~> 2.0.0'
54
+ end
55
+ Jeweler::GemcutterTasks.new
56
+ rescue LoadError
57
+ puts "Jeweler not available. Install it with: sudo gem install jeweler"
58
+ end
@@ -0,0 +1 @@
1
+ require "asset_resource"
@@ -0,0 +1,11 @@
1
+ module AssetResource
2
+ VERSION = "0.0.1"
3
+ end
4
+
5
+ if defined?(Rails)
6
+ require "asset_resource/framework/rails#{Rails::VERSION::MAJOR}"
7
+ end
8
+
9
+ if defined?(Sinatra)
10
+ require "asset_resource/framework/sinatra"
11
+ end
@@ -0,0 +1,19 @@
1
+ require "asset_resource"
2
+ require "asset_resource/middleware"
3
+
4
+ module AssetResource::Helpers
5
+ def asset_resource_stylesheets
6
+ '<link rel="stylesheet" href="/assets/stylesheets.css" />'
7
+ end
8
+
9
+ def asset_resource_javascripts
10
+ '<script type="text/javascript" src="/assets/javascripts.js"></script>'
11
+ end
12
+ end
13
+
14
+ Rails.configuration.middleware.use AssetResource::Middleware,
15
+ :base_path => Rails.root.join("public"),
16
+ :handlers => { :javascripts => "text/javascript",
17
+ :stylesheets => "text/css" }
18
+
19
+ ActionView::Base.send :include, AssetResource::Helpers
@@ -0,0 +1,24 @@
1
+ require "asset_resource"
2
+ require "asset_resource/middleware"
3
+ require "active_support"
4
+
5
+ ActiveSupport.on_load(:before_configuration) do
6
+ Rails.application.config.middleware.use AssetResource::Middleware,
7
+ :base_path => Rails.root.join("public"),
8
+ :handlers => { :javascripts => "text/javascript",
9
+ :stylesheets => "text/css" }
10
+ end
11
+
12
+ module AssetResource::Helpers
13
+ def asset_resource_stylesheets
14
+ '<link rel="stylesheet" href="/assets/stylesheets.css" />'
15
+ end
16
+
17
+ def asset_resource_javascripts
18
+ '<script type="text/javascript" src="/assets/javascripts.js"></script>'
19
+ end
20
+ end
21
+
22
+ ActiveSupport.on_load(:action_view) do
23
+ include AssetResource::Helpers
24
+ end
@@ -0,0 +1,26 @@
1
+ require "asset_resource/middleware"
2
+
3
+ module Sinatra
4
+ module AssetResource
5
+ def self.registered(app)
6
+ app.use ::AssetResource::Middleware,
7
+ :base_path => File.join(app.root, "assets"),
8
+ :handlers => { :scripts => "text/javascript",
9
+ :styles => "text/css" }
10
+
11
+ app.helpers Sinatra::AssetResource::Helpers
12
+ end
13
+
14
+ module Helpers
15
+ def asset_resource_styles
16
+ '<link rel="stylesheet" href="/assets/styles.css" />'
17
+ end
18
+
19
+ def asset_resource_scripts
20
+ '<script type="text/javascript" src="/assets/scripts.js"></script>'
21
+ end
22
+ end
23
+ end
24
+
25
+ register AssetResource
26
+ end
@@ -0,0 +1,96 @@
1
+ require "asset_resource"
2
+
3
+ class AssetResource::Middleware
4
+
5
+ attr_reader :app, :options
6
+
7
+ def initialize(app, options={})
8
+ @app = app
9
+ @options = options
10
+
11
+ if options[:handlers] then
12
+ options[:handlers].each do |handler, mime_type|
13
+ handle handler.to_sym, mime_type
14
+ end
15
+ else
16
+ handle :scripts, "text/javascript"
17
+ handle :styles, "text/css"
18
+ end
19
+
20
+ translator :less do |filename|
21
+ begin
22
+ require "less"
23
+ Less::Engine.new(File.read(filename)).to_css
24
+ rescue LoadError
25
+ raise "Tried to translate a less file but could not find the library.\nTry adding this to your Gemfile:\n gem \"less\""
26
+ end
27
+ end
28
+
29
+ translator :sass do |filename|
30
+ begin
31
+ require "sass"
32
+ Sass::Engine.new(File.read(filename), :load_paths => [File.dirname(filename)]).render
33
+ rescue LoadError
34
+ raise "Tried to translate a sass file but could not find the library.\nTry adding this to your Gemfile:\n gem \"haml\""
35
+ end
36
+ end
37
+ end
38
+
39
+ def call(env)
40
+ if env["PATH_INFO"] =~ %r{\A/assets/(.+)\B}
41
+ type = $1.split(".").first
42
+ return app.call(env) unless handles?(type)
43
+ return [200, asset_headers(type), process_files(files_for(type))]
44
+ end
45
+ app.call(env)
46
+ end
47
+
48
+ private ######################################################################
49
+
50
+ def asset_headers(type)
51
+ headers = options[:asset_headers] || { "Cache-Control" => "public, max-age=86400" }
52
+ headers.merge("Content-Type" => handlers[type.to_sym])
53
+ end
54
+
55
+ def base_path
56
+ options[:base_path] || "public"
57
+ end
58
+
59
+ def files_for(type)
60
+ Dir.glob(File.expand_path(File.join(base_path, type, "**", "*")))
61
+ end
62
+
63
+ def process_files(files)
64
+ data = files.inject("") do |accum, file|
65
+ ext = File.extname(file)[1..-1]
66
+ accum << translator(ext).call(file)
67
+ end
68
+ StringIO.new(data)
69
+ end
70
+
71
+ def handlers
72
+ @handler ||= {}
73
+ end
74
+
75
+ def handles?(type)
76
+ handlers.keys.include?(type.to_sym)
77
+ end
78
+
79
+ def handle(type, mime_type)
80
+ handlers[type.to_sym] = mime_type
81
+ end
82
+
83
+ def default_translator
84
+ lambda { |filename| File.read(filename) }
85
+ end
86
+
87
+ def translators
88
+ @translators ||= Hash.new(default_translator)
89
+ end
90
+
91
+ def translator(type, &block)
92
+ translators[type.to_sym] = block if block_given?
93
+ translators[type.to_sym]
94
+ end
95
+
96
+ end
@@ -0,0 +1,50 @@
1
+ require "spec_helper"
2
+ require "asset_resource/middleware"
3
+
4
+ describe AssetResource::Middleware do
5
+
6
+ let(:app) { lambda { |env| [ 200, {}, ['bar'] ]} }
7
+ let(:middleware) { AssetResource::Middleware.new(app, :base_path => asset_fixture) }
8
+
9
+ before(:each) do
10
+ Artifice.activate_with(middleware)
11
+ end
12
+
13
+ it "passes unhandled requests" do
14
+ RestClient.get("http://localhost/foo").to_s.should == "bar"
15
+ end
16
+
17
+ it "serves with cache headers" do
18
+ response = RestClient.get("http://localhost/assets/scripts.js")
19
+ response.headers[:cache_control].should =~ /public/
20
+ end
21
+
22
+ it "can set custom asset headers" do
23
+ middleware.options[:asset_headers] = { "X-Foo" => "Bar" }
24
+ response = RestClient.get("http://localhost/assets/scripts.js")
25
+ response.headers[:cache_control].should_not =~ /public/
26
+ response.headers[:x_foo].should == "Bar"
27
+ end
28
+
29
+ it "serves scripts" do
30
+ data = RestClient.get("http://localhost/assets/scripts.js")
31
+ data.should include "console.log('hello!')"
32
+ end
33
+
34
+ it "serves styles" do
35
+ data = RestClient.get("http://localhost/assets/styles.css")
36
+ data.should include "color: #1e5500"
37
+ data.should include "color: #5a5500"
38
+ end
39
+
40
+ it "serves scripts with the proper mime type" do
41
+ response = RestClient.get("http://localhost/assets/scripts.js")
42
+ response.headers[:content_type].should == "text/javascript"
43
+ end
44
+
45
+ it "serves styles with the proper mime type" do
46
+ response = RestClient.get("http://localhost/assets/styles.css")
47
+ response.headers[:content_type].should == "text/css"
48
+ end
49
+
50
+ end
@@ -0,0 +1,8 @@
1
+ require "spec_helper"
2
+ require "asset_resource"
3
+
4
+ describe AssetResource do
5
+ it "has a version" do
6
+ AssetResource::VERSION.should be_a String
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ require "rubygems"
2
+ require "rspec"
3
+ require "artifice"
4
+ require "rest_client"
5
+
6
+ $:.unshift "lib"
7
+
8
+ def asset_fixture(name="")
9
+ File.expand_path("../fixtures/#{name}", __FILE__)
10
+ end
11
+
12
+ Rspec.configure do |config|
13
+ config.color_enabled = true
14
+ end
metadata ADDED
@@ -0,0 +1,205 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: asset-resource
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - David Dollar
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-25 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: artifice
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 1
30
+ segments:
31
+ - 0
32
+ - 5
33
+ version: "0.5"
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: fakefs
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 21
45
+ segments:
46
+ - 0
47
+ - 2
48
+ - 1
49
+ version: 0.2.1
50
+ type: :development
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: haml
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 21
61
+ segments:
62
+ - 3
63
+ - 0
64
+ - 9
65
+ version: 3.0.9
66
+ type: :development
67
+ version_requirements: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ name: less
70
+ prerelease: false
71
+ requirement: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ hash: 53
77
+ segments:
78
+ - 1
79
+ - 2
80
+ - 21
81
+ version: 1.2.21
82
+ type: :development
83
+ version_requirements: *id004
84
+ - !ruby/object:Gem::Dependency
85
+ name: rake
86
+ prerelease: false
87
+ requirement: &id005 !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ~>
91
+ - !ruby/object:Gem::Version
92
+ hash: 49
93
+ segments:
94
+ - 0
95
+ - 8
96
+ - 7
97
+ version: 0.8.7
98
+ type: :development
99
+ version_requirements: *id005
100
+ - !ruby/object:Gem::Dependency
101
+ name: rest-client
102
+ prerelease: false
103
+ requirement: &id006 !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ~>
107
+ - !ruby/object:Gem::Version
108
+ hash: 1
109
+ segments:
110
+ - 1
111
+ - 5
112
+ - 1
113
+ version: 1.5.1
114
+ type: :development
115
+ version_requirements: *id006
116
+ - !ruby/object:Gem::Dependency
117
+ name: rcov
118
+ prerelease: false
119
+ requirement: &id007 !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ hash: 43
125
+ segments:
126
+ - 0
127
+ - 9
128
+ - 8
129
+ version: 0.9.8
130
+ type: :development
131
+ version_requirements: *id007
132
+ - !ruby/object:Gem::Dependency
133
+ name: rspec
134
+ prerelease: false
135
+ requirement: &id008 !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ~>
139
+ - !ruby/object:Gem::Version
140
+ hash: 15
141
+ segments:
142
+ - 2
143
+ - 0
144
+ - 0
145
+ version: 2.0.0
146
+ type: :development
147
+ version_requirements: *id008
148
+ description: Manage CSS/JS assets as dynamic resources rather than static files
149
+ email: ddollar@gmail.com
150
+ executables: []
151
+
152
+ extensions: []
153
+
154
+ extra_rdoc_files:
155
+ - README.md
156
+ files:
157
+ - README.md
158
+ - Rakefile
159
+ - lib/asset-resource.rb
160
+ - lib/asset_resource.rb
161
+ - lib/asset_resource/framework/rails2.rb
162
+ - lib/asset_resource/framework/rails3.rb
163
+ - lib/asset_resource/framework/sinatra.rb
164
+ - lib/asset_resource/middleware.rb
165
+ - spec/asset_resource/middleware_spec.rb
166
+ - spec/asset_resource_spec.rb
167
+ - spec/spec_helper.rb
168
+ has_rdoc: false
169
+ homepage: http://github.com/ddollar/asset-resource
170
+ licenses: []
171
+
172
+ post_install_message:
173
+ rdoc_options:
174
+ - --charset=UTF-8
175
+ require_paths:
176
+ - lib
177
+ required_ruby_version: !ruby/object:Gem::Requirement
178
+ none: false
179
+ requirements:
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ hash: 3
183
+ segments:
184
+ - 0
185
+ version: "0"
186
+ required_rubygems_version: !ruby/object:Gem::Requirement
187
+ none: false
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ hash: 3
192
+ segments:
193
+ - 0
194
+ version: "0"
195
+ requirements: []
196
+
197
+ rubyforge_project:
198
+ rubygems_version: 1.3.7
199
+ signing_key:
200
+ specification_version: 3
201
+ summary: Manage CSS/JS assets as dynamic resources rather than static files
202
+ test_files:
203
+ - spec/asset_resource/middleware_spec.rb
204
+ - spec/asset_resource_spec.rb
205
+ - spec/spec_helper.rb