webmate-sprockets 0.1.0

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/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: []