webmate-sprockets 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'sprockets', '~> 2.0'
6
+ gem 'uglifier'
7
+ gem 'closure-compiler'
8
+ gem 'yui-compressor', :require => "yui/compressor"
9
+ gem 'execjs'
10
+ gem 'therubyracer'
@@ -0,0 +1 @@
1
+ require 'webmate/sprockets'
@@ -0,0 +1,62 @@
1
+ require 'sprockets'
2
+ require 'webmate/sprockets/configuration'
3
+ require 'webmate/sprockets/asset_paths'
4
+ require 'webmate/sprockets/helpers'
5
+ require 'webmate/sprockets/static_compiler'
6
+
7
+ module Webmate
8
+ module Sprockets
9
+ def self.configure(&block)
10
+ block.call(config)
11
+ raise ArgumentError, "Cannot initialize Sprockets Environment without an app reference" if config.app.nil?
12
+
13
+ @environment = ::Sprockets::Environment.new(config.app.root)
14
+
15
+ config.paths.each do |path|
16
+ environment.append_path(File.join(config.app.root, path))
17
+ end
18
+
19
+ # require webmate assets
20
+ webmate_path = if Gem::Specification.respond_to?(:find_by_name)
21
+ Gem::Specification.find_by_name("webmate").full_gem_path
22
+ else
23
+ Gem.source_index.search("webmate").first.full_gem_path
24
+ end
25
+ ['stylesheets', 'javascripts', 'images'].each do |dir|
26
+ environment.append_path(File.join(webmate_path, 'vendor', 'assets', dir))
27
+ end
28
+
29
+ if config.compress_assets?
30
+ environment.js_compressor = Closure::Compiler.new
31
+ environment.css_compressor = YUI::CssCompressor.new
32
+ else
33
+ environment.js_compressor = false
34
+ environment.css_compressor = false
35
+ end
36
+
37
+ if config.manifest_path
38
+ path = File.join(config.app.root, config.manifest_path, "manifest.yml")
39
+ else
40
+ path = File.join(config.app.settings.public_path, 'assets', "manifest.yml")
41
+ end
42
+
43
+ if File.exist?(path)
44
+ YAML.load_file(path).each do |path, value|
45
+ config.digests[path] = value
46
+ end
47
+ end
48
+
49
+ environment.context_class.instance_eval do
50
+ include Helpers
51
+ end
52
+ end
53
+
54
+ def self.config
55
+ @config ||= Configuration.new
56
+ end
57
+
58
+ def self.environment
59
+ @environment
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,131 @@
1
+ module Webmate
2
+ module Sprockets
3
+ class AssetPaths
4
+ attr_reader :config
5
+
6
+ class AssetNotPrecompiledError < StandardError; end
7
+
8
+ def initialize(config)
9
+ @config = config
10
+ end
11
+
12
+ def asset_for(source, ext)
13
+ source = source.to_s
14
+ return nil if is_uri?(source)
15
+ source = rewrite_extension(source, nil, ext)
16
+ config.environment[source]
17
+ rescue ::Sprockets::FileOutsidePaths
18
+ nil
19
+ end
20
+
21
+ def digest_for(logical_path)
22
+ if config.digest_assets? && config.digests && (digest = config.digests[logical_path])
23
+ digest
24
+ else
25
+ if config.compile_assets?
26
+ if config.digest_assets? && asset = config.environment[logical_path]
27
+ asset.digest_path
28
+ else
29
+ logical_path
30
+ end
31
+ else
32
+ raise AssetNotPrecompiledError.new("#{logical_path} isn't precompiled")
33
+ end
34
+ end
35
+ end
36
+
37
+ def compute_public_path(source, dir, options = {})
38
+ source = source.to_s
39
+ unless is_uri?(source)
40
+ source = rewrite_extension(source, dir, options[:ext]) if options[:ext]
41
+ source = rewrite_asset_path(source, dir, options)
42
+ source = rewrite_relative_url_root(source, config.relative_url_root)
43
+ source = rewrite_host_and_protocol(source, options[:protocol])
44
+ end
45
+ source
46
+ end
47
+
48
+ def is_uri?(path)
49
+ path =~ %r{^[-a-z]+://|^cid:|^//}
50
+ end
51
+
52
+ def rewrite_host_and_protocol(source, protocol = nil)
53
+ host = compute_asset_host(source)
54
+ if host && !is_uri?(host)
55
+ if (protocol || default_protocol) == :request && !has_request?
56
+ host = nil
57
+ else
58
+ host = "#{compute_protocol(protocol)}#{host}"
59
+ end
60
+ end
61
+ host ? "#{host}#{source}" : source
62
+ end
63
+
64
+ def rewrite_relative_url_root(source, relative_url_root)
65
+ relative_url_root && !source.starts_with?("#{relative_url_root}/") ? "#{relative_url_root}#{source}" : source
66
+ end
67
+
68
+ def rewrite_asset_path(source, dir, options = {})
69
+ if source[0] == ?/
70
+ source
71
+ else
72
+ source = digest_for(source) unless options[:digest] == false
73
+ source = File.join(dir, source)
74
+ source = "/#{source}" unless source =~ /^\//
75
+ source
76
+ end
77
+ end
78
+
79
+ def rewrite_extension(source, dir, ext)
80
+ if ext && File.extname(source).empty?
81
+ "#{source}.#{ext}"
82
+ else
83
+ source
84
+ end
85
+ end
86
+
87
+ def compute_asset_host(source)
88
+ if host = config.host
89
+ if host.respond_to?(:call)
90
+ args = [source]
91
+ arity = arity_of(host)
92
+ if arity > 1 && request.nil?
93
+ invalid_asset_host!("Remove the second argument to your asset_host Proc if you do not need the request.")
94
+ end
95
+ args << current_request if (arity > 1 || arity < 0) && has_request?
96
+ host.call(*args)
97
+ else
98
+ (host =~ /%d/) ? host % (Zlib.crc32(source) % 4) : host
99
+ end
100
+ end
101
+ end
102
+
103
+ def default_protocol
104
+ config.default_protocol || (request.nil?? :relative : :request)
105
+ end
106
+
107
+ def compute_protocol(protocol)
108
+ protocol ||= default_protocol
109
+ case protocol
110
+ when :request
111
+ if request.nil?
112
+ invalid_asset_host!("The protocol requested was :request. Consider using :relative instead.")
113
+ end
114
+ request.protocol
115
+ when :relative
116
+ "//"
117
+ else
118
+ "#{protocol}://"
119
+ end
120
+ end
121
+
122
+ def arity_of(callable)
123
+ callable.respond_to?(:arity) ? callable.arity : callable.method(:call).arity
124
+ end
125
+
126
+ def invalid_asset_host!(help_message)
127
+ raise ActionController::RoutingError, "This asset host cannot be computed without a request in scope. #{help_message}"
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,71 @@
1
+ module Webmate
2
+ module Sprockets
3
+ class Configuration
4
+ DEFAULTS = {
5
+ :digest => true,
6
+ :debug => false,
7
+ :compile => false,
8
+ :compress => true,
9
+ :prefix => "assets",
10
+ :host => nil,
11
+ :relative_url_root => ENV['RACK_RELATIVE_URL_ROOT'],
12
+ :precompile => [ /\w+\.(?!js|css).+/, /application.(css|js)$/ ],
13
+ :manifest_path => "public/assets",
14
+ :app => nil,
15
+ :js_compressor => nil,
16
+ :css_compressor => nil
17
+ }
18
+ OPTIONS = DEFAULTS.keys
19
+
20
+ OPTIONS.each do |option|
21
+ define_method "#{option}=" do |value|
22
+ (@_config ||= {})[option] = value
23
+ end
24
+
25
+ define_method "#{option}" do
26
+ (@_config ||= {})[option]
27
+ end
28
+ end
29
+
30
+ [:digest, :debug, :compile, :compress].each do |option|
31
+ define_method "#{option}_assets?" do
32
+ !! @_config[option]
33
+ end
34
+ end
35
+
36
+ def initialize
37
+ @_config = DEFAULTS
38
+ @_digests = {}
39
+ @_paths = []
40
+ end
41
+
42
+ def digests
43
+ @_digests
44
+ end
45
+
46
+ def digests=(value)
47
+ @_digests = value
48
+ end
49
+
50
+ def append_path(path)
51
+ @_paths << path
52
+ end
53
+
54
+ def paths=(value)
55
+ @_paths = value.to_a
56
+ end
57
+
58
+ def paths
59
+ @_paths
60
+ end
61
+
62
+ def inspect
63
+ @_config.inspect
64
+ end
65
+
66
+ def environment
67
+ Webmate::Sprockets.environment
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,158 @@
1
+ module Webmate
2
+ module Sprockets
3
+ module Helpers
4
+ BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked autobuffer
5
+ autoplay controls loop selected hidden scoped async
6
+ defer reversed ismap seemless muted required
7
+ autofocus novalidate formnovalidate open pubdate).to_set
8
+ BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map {|attribute| attribute.to_sym })
9
+
10
+ def favicon_link_tag(source='favicon.ico', options={})
11
+ tag('link', {
12
+ :rel => 'shortcut icon',
13
+ :type => 'image/vnd.microsoft.icon',
14
+ :href => asset_path(source)
15
+ }.merge(options))
16
+ end
17
+
18
+ def image_tag(source, options = {})
19
+ digest = options.key?(:digest) ? options.delete(:digest) : config.digest_assets?
20
+
21
+ options[:src] = asset_path(source, :digest => digest)
22
+ options[:alt] = options.fetch(:alt){ image_alt(source) }
23
+
24
+ if size = options.delete(:size)
25
+ options[:width], options[:height] = size.split("x") if size =~ %r{^\d+x\d+$}
26
+ end
27
+
28
+ tag("img", options)
29
+ end
30
+
31
+ def video_tag(sources, options = {})
32
+ options
33
+
34
+ options[:poster] = asset_path(options[:poster]) if options[:poster]
35
+
36
+ if size = options.delete(:size)
37
+ options[:width], options[:height] = size.split("x") if size =~ %r{^\d+x\d+$}
38
+ end
39
+
40
+ if sources.is_a?(Array)
41
+ content_tag("video", options) do
42
+ sources.map { |source| tag("source", :src => source) }.join
43
+ end
44
+ else
45
+ options[:src] = asset_path(sources)
46
+ tag("video", options)
47
+ end
48
+ end
49
+
50
+ def audio_tag(source, options = {})
51
+ options
52
+ options[:src] = asset_path(source)
53
+ tag("audio", options)
54
+ end
55
+
56
+ def javascript_include_tag(*sources)
57
+ options = sources.extract_options!
58
+ debug = options.key?(:debug) ? options.delete(:debug) : config.debug_assets?
59
+ body = options.key?(:body) ? options.delete(:body) : false
60
+ digest = options.key?(:digest) ? options.delete(:digest) : config.digest_assets?
61
+
62
+ sources.collect do |source|
63
+ if debug && asset = asset_paths.asset_for(source, 'js')
64
+ asset.to_a.map { |dep|
65
+ src = asset_path(dep, :ext => 'js', :body => true, :digest => digest)
66
+ content_tag("script", "", { "type" => "text/javascript", "src" => src }.merge!(options))
67
+ }
68
+ else
69
+ src = asset_path(source, :ext => 'js', :body => body, :digest => digest)
70
+ content_tag("script", "", { "type" => "text/javascript", "src" => src }.merge!(options))
71
+ end
72
+ end.join("\n")
73
+ end
74
+
75
+ def stylesheet_link_tag(*sources)
76
+ options = sources.extract_options!
77
+ debug = options.key?(:debug) ? options.delete(:debug) : config.debug_assets?
78
+ body = options.key?(:body) ? options.delete(:body) : false
79
+ digest = options.key?(:digest) ? options.delete(:digest) : config.digest_assets?
80
+
81
+ sources.collect do |source|
82
+ if debug && asset = asset_paths.asset_for(source, 'css')
83
+ asset.to_a.map { |dep|
84
+ href = asset_path(dep, :ext => 'css', :body => true, :protocol => :request, :digest => digest)
85
+ tag("link", { "rel" => "stylesheet", "type" => "text/css", "media" => "screen", "href" => href }.merge!(options))
86
+ }
87
+ else
88
+ href = asset_path(source, :ext => 'css', :body => body, :protocol => :request, :digest => digest)
89
+ tag("link", { "rel" => "stylesheet", "type" => "text/css", "media" => "screen", "href" => href }.merge!(options))
90
+ end
91
+ end.join("\n")
92
+ end
93
+
94
+ def asset_path(source, options={})
95
+ source = source.logical_path if source.respond_to?(:logical_path)
96
+ digest = options.key?(:digest) ? options.delete(:digest) : config.digest_assets?
97
+ path = asset_paths.compute_public_path(source, config.prefix, options.merge(:body => true, :digest => digest))
98
+ options[:body] ? "#{path}?body=1" : path
99
+ end
100
+
101
+ def tag(name, options = nil, open = false, escape = true)
102
+ "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}"
103
+ end
104
+
105
+ def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
106
+ if block_given?
107
+ options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
108
+ content_tag_string(name, block.call, options, escape)
109
+ else
110
+ content_tag_string(name, content_or_options_with_block, options, escape)
111
+ end
112
+ end
113
+
114
+ private
115
+
116
+ def asset_paths
117
+ @asset_paths ||= AssetPaths.new(Webmate::Sprockets.config)
118
+ end
119
+
120
+ def config
121
+ Webmate::Sprockets.config
122
+ end
123
+
124
+ def tag_options(options, escape = true)
125
+ unless options.blank?
126
+ attrs = []
127
+ options.each_pair do |key, value|
128
+ if key.to_s == 'data' && value.is_a?(Hash)
129
+ value.each do |k, v|
130
+ if !v.is_a?(String) && !v.is_a?(Symbol)
131
+ v = v.to_json
132
+ end
133
+ v = ERB::Util.html_escape(v) if escape
134
+ attrs << %(data-#{k.to_s.dasherize}="#{v}")
135
+ end
136
+ elsif BOOLEAN_ATTRIBUTES.include?(key)
137
+ attrs << %(#{key}="#{key}") if value
138
+ elsif !value.nil?
139
+ final_value = value.is_a?(Array) ? value.join(" ") : value
140
+ final_value = ERB::Util.html_escape(final_value) if escape
141
+ attrs << %(#{key}="#{final_value}")
142
+ end
143
+ end
144
+ " #{attrs.sort * ' '}" unless attrs.empty?
145
+ end
146
+ end
147
+
148
+ def content_tag_string(name, content, options, escape = true)
149
+ tag_options = tag_options(options, escape) if options
150
+ "<#{name}#{tag_options}>#{escape ? ERB::Util.h(content) : content}</#{name}>"
151
+ end
152
+
153
+ def image_alt(source)
154
+ File.basename(source, '.*').sub(%r-[[:xdigit:]]{32}\z-, '')
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,41 @@
1
+ require "fileutils"
2
+
3
+ namespace :assets do
4
+ desc "Compile all the assets named in config.assets.precompile"
5
+ task :precompile do
6
+ Rake::Task["assets:clean:all"].invoke
7
+ Rake::Task["assets:precompile:all"].invoke
8
+ end
9
+
10
+ namespace :precompile do
11
+ task :all => ["environment"] do
12
+ config = Webmate::Sprockets.config
13
+ config.compile ||= true
14
+ config.digest ||= true
15
+ config.digests ||= {}
16
+
17
+ env = Webmate::Sprockets.environment
18
+ target = File.join(config.app.settings.public_path, config.prefix)
19
+ compiler = Webmate::Sprockets::StaticCompiler.new(env,
20
+ target,
21
+ config.precompile,
22
+ :manifest_path => config.manifest_path,
23
+ :digest => config.digest,
24
+ :manifest => true)
25
+ compiler.compile
26
+ end
27
+ end
28
+
29
+ desc "Remove compiled assets"
30
+ task :clean do
31
+ Rake::Task["assets:clean:all"].invoke
32
+ end
33
+
34
+ namespace :clean do
35
+ task :all => ["environment"] do
36
+ config = Webmate::Sprockets.config
37
+ public_asset_path = File.join(config.app.settings.public_path, config.prefix)
38
+ rm_rf public_asset_path, :secure => true
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,64 @@
1
+ module Webmate
2
+ module Sprockets
3
+ class StaticCompiler
4
+ require 'fileutils'
5
+ attr_accessor :env, :target, :paths
6
+
7
+ def initialize(env, target, paths, options = {})
8
+ @env = env
9
+ @target = target
10
+ @paths = paths
11
+ @digest = options.key?(:digest) ? options.delete(:digest) : true
12
+ @manifest = options.key?(:manifest) ? options.delete(:manifest) : true
13
+ @manifest_path = options.delete(:manifest_path) || target
14
+ end
15
+
16
+ def compile
17
+ manifest = {}
18
+ env.each_logical_path do |logical_path|
19
+ next unless compile_path?(logical_path)
20
+ if asset = env.find_asset(logical_path)
21
+ manifest[logical_path] = write_asset(asset)
22
+ end
23
+ end
24
+ write_manifest(manifest) if @manifest
25
+ end
26
+
27
+ def write_manifest(manifest)
28
+ FileUtils.mkdir_p(@manifest_path)
29
+ File.open("#{@manifest_path}/manifest.yml", 'wb') do |f|
30
+ YAML.dump(manifest, f)
31
+ end
32
+ end
33
+
34
+ def write_asset(asset)
35
+ path_for(asset).tap do |path|
36
+ filename = File.join(target, path)
37
+ FileUtils.mkdir_p File.dirname(filename)
38
+ asset.write_to(filename)
39
+ asset.write_to("#{filename}.gz") if filename.to_s =~ /\.(css|js)$/
40
+ end
41
+ end
42
+
43
+ def compile_path?(logical_path)
44
+ answer = false
45
+ paths.each do |path|
46
+ case path
47
+ when Regexp
48
+ answer = path.match(logical_path)
49
+ when Proc
50
+ answer = path.call(logical_path)
51
+ else
52
+ answer = File.fnmatch(path.to_s, logical_path)
53
+ end
54
+ break if answer
55
+ end
56
+ answer
57
+ end
58
+
59
+ def path_for(asset)
60
+ @digest ? asset.digest_path : asset.logical_path
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,5 @@
1
+ module Webmate
2
+ module Sprockets
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "webmate/sprockets/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "webmate-sprockets"
7
+ s.version = Webmate::Sprockets::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["thegorgon", 'Iskander Haziev']
10
+ s.email = ["jessereiss@gmail.com", 'gvalmon@gmail.com']
11
+ s.homepage = "https://github.com/webmaterb/webmate-sprockets"
12
+ s.summary = %q{Webmate helpers for Sprockets integration.}
13
+ s.description = %q{Use Sprockets effectively with Webmate.}
14
+
15
+ s.rubyforge_project = s.name
16
+
17
+ s.add_runtime_dependency 'sprockets', '~> 2.0'
18
+
19
+ s.files = [
20
+ "Gemfile",
21
+ "webmate-sprockets.gemspec",
22
+ "lib/webmate-sprockets.rb",
23
+ "lib/webmate/sprockets.rb",
24
+ "lib/webmate/sprockets/asset_paths.rb",
25
+ "lib/webmate/sprockets/configuration.rb",
26
+ "lib/webmate/sprockets/helpers.rb",
27
+ "lib/webmate/sprockets/rake.rb",
28
+ "lib/webmate/sprockets/static_compiler.rb",
29
+ "lib/webmate/sprockets/version.rb"
30
+ ]
31
+
32
+ s.require_paths << "lib"
33
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: webmate-sprockets
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - thegorgon
9
+ - Iskander Haziev
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-05-07 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: sprockets
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '2.0'
31
+ description: Use Sprockets effectively with Webmate.
32
+ email:
33
+ - jessereiss@gmail.com
34
+ - gvalmon@gmail.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - Gemfile
40
+ - webmate-sprockets.gemspec
41
+ - lib/webmate-sprockets.rb
42
+ - lib/webmate/sprockets.rb
43
+ - lib/webmate/sprockets/asset_paths.rb
44
+ - lib/webmate/sprockets/configuration.rb
45
+ - lib/webmate/sprockets/helpers.rb
46
+ - lib/webmate/sprockets/rake.rb
47
+ - lib/webmate/sprockets/static_compiler.rb
48
+ - lib/webmate/sprockets/version.rb
49
+ homepage: https://github.com/webmaterb/webmate-sprockets
50
+ licenses: []
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project: webmate-sprockets
70
+ rubygems_version: 1.8.25
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Webmate helpers for Sprockets integration.
74
+ test_files: []