slight_assets 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ require 'rbconfig'
2
+
3
+ class SlightAssetsGenerator < ::Rails::Generator::Base
4
+ def manifest
5
+ record do |m|
6
+ m.file "config/assets.yml", "config/assets.yml"
7
+ m.file "config/initializers/assets.rb", "config/initializers/assets.rb"
8
+ end
9
+ end
10
+
11
+ def self.gem_root
12
+ File.expand_path('../../../', __FILE__)
13
+ end
14
+
15
+ def self.source_root
16
+ File.join(gem_root, 'templates', 'install')
17
+ end
18
+
19
+ def source_root
20
+ self.class.source_root
21
+ end
22
+
23
+ private
24
+
25
+ def banner
26
+ "Usage: #{$0} slight_assets"
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ module SlightAssets
2
+ autoload :Util, "slight_assets/util"
3
+ autoload :Rails, "slight_assets/rails"
4
+ autoload :Cfg, "slight_assets/settings"
5
+ autoload :JsReducer, "slight_assets/js_reducer"
6
+ autoload :VERSION, "slight_assets/version"
7
+ end
@@ -0,0 +1,85 @@
1
+ module SlightAssets
2
+ class JsReducer
3
+ BYTE_RANGE = 32..127
4
+ BASE_NUMBER = BYTE_RANGE.count
5
+ FETCH_RANGE = BASE_NUMBER ** 2
6
+ LOOKUP_CHAR = "`"
7
+ ESCAPABLE_CHARS = ["\\", "\"", "\r", "\n"].freeze
8
+
9
+ def compress(js_content)
10
+ content = reduce(js_content)
11
+ return js_content if content == js_content
12
+ func = 'function(x){var b="",p=0,c,l,L=x.length,m="`";while(p<L)b+=(c=x[p++])!=m?c:(l=x.charCodeAt(p++)-31)>1?b.substr(b.length-x.charCodeAt(p++)*96-x.charCodeAt(p++)+3104-l,l):m;return b}'
13
+ content = content.gsub(/([\\"])/, '\\\\\\1').gsub(/\r/, "\\r").gsub(/\n/, "\\n")
14
+ "eval((#{func})(\"#{content}\"))"
15
+ end
16
+
17
+ def reduce(js_content)
18
+ max_cropsize = BASE_NUMBER
19
+ content = str_as_utf8(js_content)
20
+ return js_content if content.nil?
21
+ output, index, limit = "", -1, content.size
22
+ while (index+=1) < limit
23
+ i, chars = -1, str_as_utf8("")
24
+ cropindex, cropsize, s = nil, 0, 0
25
+ while (i+=1) < max_cropsize && index + i < limit
26
+ chars << (c = content[index+i])
27
+ next if s < 5 && (s += (ESCAPABLE_CHARS.include?(c) ? 2 : c.bytesize) ) < 5
28
+ max_start = index - chars.size
29
+ start = [0, max_start - FETCH_RANGE].max
30
+ if (pos = content.index(chars, start)) && pos <= max_start
31
+ cropindex, cropsize = pos, chars.size
32
+ end
33
+ end
34
+ if cropindex.nil?
35
+ output << content[index]
36
+ output << " " if content[index] == LOOKUP_CHAR
37
+ else
38
+ max_start = [0, index - cropsize].max
39
+ chars = str_as_utf8(content[cropindex, cropsize])
40
+ cropindex = pos while (pos = content.index(chars, cropindex + 1)) && pos <= max_start
41
+ output << LOOKUP_CHAR
42
+ output << BYTE_RANGE.last - max_cropsize + cropsize
43
+ offset = (index - cropindex) - cropsize
44
+ output << BYTE_RANGE.first + (offset / BASE_NUMBER)
45
+ output << BYTE_RANGE.first + (offset % BASE_NUMBER)
46
+ index += cropsize - 1
47
+ end
48
+ end
49
+ output
50
+ end
51
+
52
+ if RUBY_VERSION =~ /\A1\.[0-8]/
53
+ begin
54
+ require "utf8"
55
+ def str_as_utf8(str)
56
+ str.as_utf8
57
+ end
58
+ rescue LoadError
59
+ def str_as_utf8(str)
60
+ a = str.is_a?(Array) ? str : str.scan(/./mu)
61
+ class << a
62
+ def index(chars, start)
63
+ return nil if start >= size
64
+ i, s, cs = start - 1, size, chars.size
65
+ while (i+=1) < s
66
+ next if self[i] != chars[0]
67
+ return i if cs == 1
68
+ j = 0
69
+ while (j+=1) < cs && i + j < s
70
+ break if self[i+j] != chars[j]
71
+ return i if j + 1 == cs
72
+ end
73
+ end
74
+ end
75
+ end
76
+ a
77
+ end
78
+ end
79
+ else
80
+ def str_as_utf8(str)
81
+ str
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,79 @@
1
+ module SlightAssets
2
+ module Rails
3
+ def init!
4
+ ActionView::Helpers::AssetTagHelper.send :include, HelperMethods
5
+ end
6
+ module_function :init!
7
+
8
+ module HelperMethods
9
+ def self.included(base)
10
+ base.class_eval do
11
+ alias_method_chain :write_asset_file_contents, :static_compressed_file
12
+ alias_method_chain :javascript_src_tag, :static_compressed_file
13
+ alias_method_chain :stylesheet_tag, :static_compressed_file
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def write_asset_file_contents_with_static_compressed_file(joined_asset_path, asset_paths)
20
+ minify = false
21
+ asset_paths = asset_paths.map do |asset_path|
22
+ p = asset_path.to_s
23
+ if p =~ /\.min\./
24
+ asset_path
25
+ else
26
+ p = p.gsub(/\.(js|css)(\?\w+)?\z/, '.min.\1\2')
27
+ if ::File.exists?(asset_file_path(p))
28
+ p
29
+ else
30
+ minify = true
31
+ asset_path
32
+ end
33
+ end
34
+ end
35
+ minified_joined_asset_path = joined_asset_path.gsub(/(?:\.min)?\.(js|css)\z/, '.min.\1')
36
+ already_existed = File.exists?(minified_joined_asset_path)
37
+ r = write_asset_file_contents_without_static_compressed_file(minify ? joined_asset_path : minified_joined_asset_path, asset_paths)
38
+ if minify && ! already_existed
39
+ SlightAssets::Util.async_write_static_compressed_file(joined_asset_path)
40
+ else
41
+ SlightAssets::Util.write_static_gzipped_file(minified_joined_asset_path)
42
+ end
43
+ r
44
+ end
45
+
46
+ def javascript_src_tag_with_static_compressed_file(source, options)
47
+ unless source =~ /\A(?:\w+:)?\/\//
48
+ asset_path = path_to_javascript(source).split('?').first
49
+ file_path = asset_file_path(asset_path)
50
+ if asset_path.end_with?(".js") && asset_path !~ /\.min\./
51
+ compressed_path = asset_path.gsub(/\.js\z/, '.min.js')
52
+ if ::File.exists?(asset_file_path(compressed_path))
53
+ source = compressed_path unless ::File.exists?("#{file_path}.locked")
54
+ elsif ::File.exists?(file_path)
55
+ SlightAssets::Util.async_write_static_compressed_file(file_path)
56
+ end
57
+ end
58
+ end
59
+ javascript_src_tag_without_static_compressed_file(source, options)
60
+ end
61
+
62
+ def stylesheet_tag_with_static_compressed_file(source, options)
63
+ unless source =~ /\A(?:\w+:)?\/\//
64
+ asset_path = path_to_stylesheet(source).split('?').first
65
+ file_path = asset_file_path(asset_path)
66
+ if asset_path.end_with?(".css") && asset_path !~ /\.min\./
67
+ compressed_path = asset_path.gsub(/\.css\z/, '.min.css')
68
+ if ::File.exists?(asset_file_path(compressed_path))
69
+ source = compressed_path unless ::File.exists?("#{file_path}.locked")
70
+ elsif ::File.exists?(file_path)
71
+ SlightAssets::Util.async_write_static_compressed_file(file_path)
72
+ end
73
+ end
74
+ end
75
+ stylesheet_tag_without_static_compressed_file(source, options)
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,112 @@
1
+ namespace :asset do
2
+ namespace :compress do
3
+ task :pre => :environment do
4
+ require "slight_assets"
5
+ class AssetWriter
6
+ include ::SlightAssets::Util
7
+ attr_reader :image_report
8
+ def initialize
9
+ @image_report = {}
10
+ end
11
+ def write_compressed_file(file)
12
+ write_static_compressed_file(file)
13
+ end
14
+ def js_list
15
+ unless defined?(@js_list)
16
+ @js_list = []
17
+ (SlightAssets::Cfg.minify_assets? || []).each do |mask|
18
+ if mask =~ /\A([+-])?\s*(.*\.js)\z/
19
+ oper = $1 || "+"
20
+ files_mask = [::Rails.root, "public", "javascripts", $2]
21
+ @js_list = @js_list.send(oper, FileList[File.join(*files_mask)])
22
+ end
23
+ end
24
+ files_mask = [::Rails.root, "public", "javascripts", "**", "*.min.js"]
25
+ @js_list = (@js_list - FileList[File.join(*files_mask)]).uniq.sort
26
+ end
27
+ @js_list
28
+ end
29
+ def css_list
30
+ unless defined?(@css_list)
31
+ @css_list = []
32
+ (SlightAssets::Cfg.minify_assets? || []).each do |mask|
33
+ if mask =~ /\A([+-])?\s*(.*\.css)\z/
34
+ oper = $1 || "+"
35
+ files_mask = [::Rails.root, "public", "stylesheets", $2]
36
+ @css_list = @css_list.send(oper, FileList[File.join(*files_mask)])
37
+ end
38
+ end
39
+ files_mask = [::Rails.root, "public", "stylesheets", "**", "*.min.css"]
40
+ @css_list = (@css_list - FileList[File.join(*files_mask)]).uniq.sort
41
+ end
42
+ @css_list
43
+ end
44
+ end
45
+ end
46
+
47
+ desc "Compress all JS files from your Rails application"
48
+ task :js => :pre do
49
+ puts "=" * 80
50
+ if SlightAssets::Util.js_compressor.nil?
51
+ puts "WARN: No JS compressor was found"
52
+ exit 1
53
+ end
54
+ writer = AssetWriter.new
55
+ jslist = writer.js_list
56
+ originalsize, compressedsize = 0, 0
57
+ start_time = Time.now
58
+ jslist.each do |jsfile|
59
+ print "Compressing #{jsfile[(Rails.root.to_s.size+1)..-1]}"
60
+ time = Time.now
61
+ minfile = writer.write_compressed_file(jsfile).chomp(".gz")
62
+ originalsize += jssize = File.size(jsfile)
63
+ compressedsize += minsize = File.size(minfile)
64
+ percent = jssize.zero? ? 100 : (100.0 * minsize / jssize).round
65
+ puts " (#{Time.now - time}s)\n -> #{jssize} bytes to #{minsize} bytes (#{percent}% size)"
66
+ end
67
+ if jslist.any?
68
+ puts "Total #{jslist.size} JS files were compressed"
69
+ percent = originalsize.zero? ? 100 : (100.0 * compressedsize / originalsize).round
70
+ puts " -> reduced from #{originalsize} bytes to #{compressedsize} bytes (#{percent}% size total, #{originalsize - compressedsize} bytes saved)"
71
+ end
72
+ puts "Elapsed time: #{Time.now - start_time}s"
73
+ end
74
+
75
+ desc "Compress all CSS files from your Rails application"
76
+ task :css => :pre do
77
+ puts "=" * 80
78
+ if SlightAssets::Util.css_compressor.nil?
79
+ puts "WARN: No CSS compressor was found"
80
+ exit 1
81
+ end
82
+ writer = AssetWriter.new
83
+ csslist = writer.css_list
84
+ start_time = Time.now
85
+ csslist.each do |cssfile|
86
+ print "Compressing #{cssfile[(Rails.root.to_s.size+1)..-1]}"
87
+ time = Time.now
88
+ minfile = writer.write_compressed_file(cssfile).chomp(".gz")
89
+ csssize = File.size(cssfile)
90
+ minsize = File.size(minfile)
91
+ percent = csssize.zero? ? 100 : (100.0 * minsize / csssize).round
92
+ puts " (#{Time.now - time}s)\n -> #{csssize} bytes to #{minsize} bytes (#{percent}% size)"
93
+ end
94
+ puts "Total: #{csslist.size} CSS files were compressed" if csslist.any?
95
+ puts "Elapsed time: #{Time.now - start_time}s"
96
+ if writer.image_report.any?
97
+ puts "=" * 80
98
+ writer.image_report.each_pair do |image_file, report|
99
+ refs = report[:found_in].size
100
+ puts "Image: #{image_file[(Rails.public_path.size)..-1]} (#{"\033[1;31m" unless refs == 1}#{refs} occurrence#{"s" unless refs == 1}\033[0m)"
101
+ report[:found_in].each_pair do |css_file, count|
102
+ mode = report[:exists] ? (report[:embeddable] && count == 1 ? "embedded" : "\033[0;33mnot embedded\033[0m") : "\033[0;31mnot found\033[0m"
103
+ puts " found in #{css_file[(Rails.public_path.size)..-1]} (#{count} ref#{"s" unless count == 1}, #{mode})"
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ desc "Compress all JS and CSS files from your Rails application"
111
+ task :compress => ["compress:js", "compress:css"]
112
+ end
@@ -0,0 +1,43 @@
1
+ slight_asset: &slight_asset
2
+
3
+ # Maximum embedded file size
4
+ # The limit file size to decide whether or not to embed
5
+ # Must be less than or equal to "32kB"
6
+ maximum_embedded_file_size: "32kB"
7
+
8
+ # Scope of assets to minify in batch process (rake).
9
+ # The prefix "-" indicates the files to exclude from minifying.
10
+ # Keep in mind that the sequence matters.
11
+ minify_assets:
12
+ - **/*.js
13
+ - -**/ckeditor/**/*.js
14
+ - **/*.css
15
+ # in the end, the masks below will be used for cleaning (even if omitted).
16
+ - -**/*.min.js
17
+ - -**/*.min.css
18
+
19
+ # Absolute MHTML base href (Optional)
20
+ # If present, the CSS images that was referenced twice or more
21
+ # will be embedded inside a MHTML block
22
+ #mhtml_base_href: "http://localhost:3000"
23
+
24
+ # JavaScript Reducer (Optional)
25
+ # This mode enables obfuscation for JavaScript compression, reducing
26
+ # even more the file size.
27
+ # Sets the JavaScript reduce mode:
28
+ # "rake" - Reduce only when executing rake task (asset:compress:js)
29
+ # true - Reduce at runtime or when executing rake
30
+ # false - Don't reduce JavaScript's
31
+ js_reducer: false
32
+
33
+ development:
34
+ slight_asset:
35
+ <<: *slight_asset
36
+
37
+ test:
38
+ slight_asset:
39
+ <<: *slight_asset
40
+
41
+ production:
42
+ slight_asset:
43
+ <<: *slight_asset
@@ -0,0 +1,57 @@
1
+ require "yaml"
2
+
3
+ module SlightAssets
4
+ class Config
5
+ attr_reader :config
6
+ def initialize
7
+ @config = {}
8
+ end
9
+
10
+ def method_missing(name, *args)
11
+ sname = name.to_s
12
+ case sname
13
+ when /\?$/
14
+ @config[$`]
15
+ when /\=$/
16
+ @config[$`] = args.first
17
+ else
18
+ return @config[sname] if @config.has_key?(sname)
19
+ super
20
+ end
21
+ end
22
+
23
+ def load_config(path)
24
+ return @config unless File.exists? path
25
+ hash = YAML.load_file(path)
26
+ hash = hash[::Rails.env] || hash if defined?(::Rails)
27
+ @config.merge! hash["slight_asset"] if hash.has_key?("slight_asset")
28
+ rescue TypeError => e
29
+ puts "could not load #{path}: #{e.inspect}"
30
+ end
31
+
32
+ def maximum_embedded_file_size
33
+ unless defined?(@maximum_embedded_file_size)
34
+ c = @config["maximum_embedded_file_size"]
35
+ if c.is_a?(Fixnum)
36
+ @maximum_embedded_file_size = c
37
+ elsif c =~ /\A(\d+)\s*(\w+)\z/
38
+ c = $1.to_i
39
+ case $2
40
+ when "kB", "kb"
41
+ c = c * 1_024
42
+ end
43
+ @maximum_embedded_file_size = [c, 32 * 1_024].min
44
+ end
45
+ end
46
+ @maximum_embedded_file_size
47
+ end
48
+
49
+ def url_matcher
50
+ /url\(['"]?(.*?)(?:\?\d+)?['"]?\)/
51
+ end
52
+ end
53
+
54
+ Cfg = Config.new
55
+ Cfg.load_config File.expand_path(File.join(*%w[.. settings default_config.yml]), __FILE__)
56
+ Cfg.load_config ::Rails.root.join(*%w[config assets.yml]) if defined?(::Rails)
57
+ end
@@ -0,0 +1,243 @@
1
+ require "base64"
2
+ require "zlib"
3
+
4
+ module SlightAssets
5
+ module Util
6
+ def write_static_gzipped_file(file_path, content = nil)
7
+ return file_path if file_path.nil? || file_path.end_with?(".gz") || ! File.exists?(file_path)
8
+ zip_path = "#{file_path}.gz"
9
+ return zip_path if File.exists?(zip_path)
10
+ content = File.read(file_path) if content.nil?
11
+ Zlib::GzipWriter.open(zip_path, Zlib::BEST_COMPRESSION) {|f| f.write(content) }
12
+ # Set mtime to the latest of the file to allow for
13
+ # consistent ETag without a shared filesystem.
14
+ mt = File.mtime(file_path)
15
+ File.utime(mt, mt, zip_path)
16
+ zip_path
17
+ end
18
+ module_function :write_static_gzipped_file
19
+
20
+ def write_static_minified_asset(file_path)
21
+ return file_path if file_path.nil? || file_path =~ /\.min\./ || file_path !~ /\.(?:js|css)\z/ || ! File.exists?(file_path)
22
+ min_path = file_path.gsub(/\.(js|css)\z/, '.min.\1')
23
+ compressor = nil
24
+ case extension = $1
25
+ when "css"
26
+ compressor = css_compressor
27
+ when "js"
28
+ compressor = js_compressor
29
+ end
30
+ return file_path if compressor.nil?
31
+ content = File.read(file_path)
32
+ c = compressor.compress(content)
33
+ content = c if c.bytesize < content.bytesize
34
+ content = embed_images(content, min_path) if extension == "css"
35
+ reduced_content = content
36
+ if extension == "js"
37
+ reduced_content = js_reduce(content)
38
+ reduced_content = content if reduced_content.bytesize > content.bytesize
39
+ end
40
+ File.open(min_path, "w") { |f| f.write(reduced_content) }
41
+ mt = File.mtime(file_path)
42
+ File.utime(mt, mt, min_path)
43
+ [min_path, content]
44
+ end
45
+ module_function :write_static_minified_asset
46
+
47
+ def js_reduce(content)
48
+ unless (Cfg.js_reducer? == "rake" && is_rake?) || Cfg.js_reducer? == true
49
+ content
50
+ else
51
+ JsReducer.new.compress(content)
52
+ end
53
+ end
54
+ module_function :js_reduce
55
+
56
+ def embed_images(content, file_path)
57
+ return content if file_path =~ /\A(?:\w+:)?\/\//
58
+ images = extract_images(content, file_path)
59
+ file_url = asset_url(file_path)
60
+ image_contents = {}
61
+ multipart = ["/*\r\nContent-Type: multipart/related; boundary=\"MHTML_IMAGES\"\r\n"]
62
+ replace_imports = Cfg.replace_css_imports?
63
+ content = content.gsub(Cfg.url_matcher) do |url_match|
64
+ image_path = $1
65
+ quot = (url_match =~ /"/ ? "\"" : "")
66
+ if image_path =~ /\A(?:[\\\/]|\w+:)/
67
+ url_match
68
+ elsif image_path =~ /(\.min)?\.css\z/ && replace_imports
69
+ if $1
70
+ url_match
71
+ elsif File.exists?(asset_expand_path(image_path, file_path))
72
+ "url(#{quot}#{image_path.gsub(/\.css\z/, ".min.css")}#{quot})"
73
+ else
74
+ url_match
75
+ end
76
+ else
77
+ image_file_path = asset_expand_path(image_path, file_path)
78
+ if (mt = image_mime_type(image_path)) &&
79
+ (encode64 = encoded_file_contents(image_file_path, file_path))
80
+ if image_contents[image_file_path].nil?
81
+ part_name = "img#{multipart.size}_#{File.basename(image_file_path)}"
82
+ image_contents[image_file_path] = [part_name, encode64]
83
+ else
84
+ part_name = image_contents[image_file_path].first
85
+ end
86
+ if images[image_file_path] > 1
87
+ if file_url
88
+ multipart << [
89
+ "\r\n--MHTML_IMAGES",
90
+ "\r\nContent-Location: ",
91
+ part_name,
92
+ "\r\nContent-Type: ",
93
+ mt,
94
+ "\r\nContent-Transfer-Encoding: base64\r\n\r\n",
95
+ encode64
96
+ ]
97
+ "url(#{quot}mhtml:#{file_url}!#{part_name}#{quot})"
98
+ else
99
+ url_match
100
+ end
101
+ else
102
+ "url(#{quot}data:#{mt};base64,#{encode64}#{quot})"
103
+ end
104
+ else
105
+ url_match
106
+ end
107
+ end
108
+ end
109
+ if multipart.size > 1
110
+ content = content.gsub(/(\*?)(background-image:[^;\}]*?url\("?mhtml)/, '*\2')
111
+ (multipart + ["\r\n--MHTML_IMAGES--\r\n*/\r\n", content]).flatten.join("")
112
+ else
113
+ content
114
+ end
115
+ end
116
+ module_function :embed_images
117
+
118
+ def asset_url(file_path)
119
+ if defined?(::Rails) && file_path.start_with?(::Rails.public_path) && Cfg.mhtml_base_href?
120
+ URI.join(Cfg.mhtml_base_href, file_path[(::Rails.public_path.size)..-1])
121
+ end
122
+ end
123
+ module_function :asset_url
124
+
125
+ def extract_images(content, file_path)
126
+ images = {}
127
+ content.scan(Cfg.url_matcher).flatten.each do |image_path|
128
+ image_file_path = asset_expand_path(image_path, file_path)
129
+ images[image_file_path] = (images[image_file_path] || 0) + 1
130
+ end
131
+ images
132
+ end
133
+ module_function :extract_images
134
+
135
+ def asset_expand_path(relative_asset_path, absolute_source_file_path)
136
+ File.expand_path(File.join("..", relative_asset_path), absolute_source_file_path)
137
+ end
138
+ module_function :asset_expand_path
139
+
140
+ def image_mime_type(path)
141
+ return if path !~ /\.([^\.]+)$/
142
+ case $1.downcase.to_sym
143
+ when :jpg, :jpeg
144
+ "image/jpeg"
145
+ when :png
146
+ "image/png"
147
+ when :gif
148
+ "image/gif"
149
+ when :tif, :tiff
150
+ "image/tiff"
151
+ end
152
+ end
153
+ module_function :image_mime_type
154
+
155
+ def encoded_file_contents(file_path, css_file_path = nil)
156
+ if css_file_path && is_rake?
157
+ @image_report[file_path] ||= {:found_in => {}}
158
+ @image_report[file_path][:found_in][css_file_path] =
159
+ (@image_report[file_path][:found_in][css_file_path] || 0) + 1
160
+ if @image_report[file_path][:exists] = File.exists?(file_path)
161
+ @image_report[file_path][:embeddable] =
162
+ File.size(file_path) <= Cfg.maximum_embedded_file_size
163
+ end
164
+ end
165
+ if File.exists?(file_path) && File.size(file_path) <= Cfg.maximum_embedded_file_size
166
+ Base64.encode64(File.read(file_path)).gsub(/\n/, "")
167
+ end
168
+ end
169
+ module_function :encoded_file_contents
170
+
171
+ def is_runtime?
172
+ ! is_rake?
173
+ end
174
+ module_function :is_runtime?
175
+
176
+ def is_rake?
177
+ defined?(@image_report) && @image_report.is_a?(Hash)
178
+ end
179
+ module_function :is_rake?
180
+
181
+ def async_write_static_compressed_file(file_path, &block)
182
+ lock_file_path = "#{file_path}.locked"
183
+ return if File.exists?(lock_file_path) && File.mtime(lock_file_path) > (Time.now - 120)
184
+ File.open(lock_file_path, "w"){} # touch
185
+ Thread.new do
186
+ begin
187
+ file_path = write_static_compressed_file(file_path)
188
+ ensure
189
+ File.delete(lock_file_path)
190
+ end
191
+ end
192
+ end
193
+ module_function :async_write_static_compressed_file
194
+
195
+ def write_static_compressed_file(file_path)
196
+ file_path, content = write_static_minified_asset(file_path)
197
+ file_path = write_static_gzipped_file(file_path, content)
198
+ end
199
+ module_function :write_static_compressed_file
200
+
201
+ def js_compressor
202
+ closure_compiler_js_compressor || yui_js_compressor
203
+ end
204
+ module_function :js_compressor
205
+
206
+ def css_compressor
207
+ yui_css_compressor
208
+ end
209
+ module_function :css_compressor
210
+
211
+ protected
212
+
213
+ begin
214
+ require "closure-compiler"
215
+ def closure_compiler_js_compressor
216
+ Closure::Compiler.new
217
+ end
218
+ rescue LoadError => e
219
+ STDERR.puts "WARN: #{e.message}"
220
+ def closure_compiler_js_compressor
221
+ end
222
+ end
223
+ module_function :closure_compiler_js_compressor
224
+
225
+ begin
226
+ require "yui/compressor"
227
+ def yui_js_compressor
228
+ YUI::JavaScriptCompressor.new
229
+ end
230
+ def yui_css_compressor
231
+ YUI::CssCompressor.new
232
+ end
233
+ rescue LoadError => e
234
+ STDERR.puts "WARN: #{e.message}"
235
+ def yui_js_compressor
236
+ end
237
+ def yui_css_compressor
238
+ end
239
+ end
240
+ module_function :yui_js_compressor
241
+ module_function :yui_css_compressor
242
+ end
243
+ end
@@ -0,0 +1,6 @@
1
+ module SlightAssets
2
+ version = nil
3
+ version = $1 if ::File.expand_path('../..', __FILE__) =~ /\/slight_assets-(\d[\w\.]+)/
4
+ version = ::StepUp::Driver::Git.new.last_version_tag if version.nil? && ::File.exists?(::File.expand_path('../../../.git', __FILE__))
5
+ VERSION = version.gsub(/^v?([^\+]+)\+?\d*$/, '\1')
6
+ end
@@ -0,0 +1 @@
1
+ require "slight_assets/base"
@@ -0,0 +1,42 @@
1
+ slight_asset: &slight_asset
2
+
3
+ # Maximum embedded file size
4
+ # The limit file size to decide whether or not to embed
5
+ # Must be less than or equal to "32kB"
6
+ maximum_embedded_file_size: "32kB"
7
+
8
+ # Scope of assets to minify in batch process (rake).
9
+ # The prefix "-" indicates the files to exclude from minifying.
10
+ # Keep in mind that the sequence matters.
11
+ minify_assets:
12
+ - **/*.js
13
+ - **/*.css
14
+ # in the end, the masks below will be used for cleaning (even if omitted).
15
+ - -**/*.min.js
16
+ - -**/*.min.css
17
+
18
+ # Absolute MHTML base href (Optional)
19
+ # If present, the CSS images that was referenced twice or more
20
+ # will be embedded inside a MHTML block
21
+ #mhtml_base_href: "http://localhost:3000"
22
+
23
+ # JavaScript Reducer (Optional)
24
+ # This mode enables obfuscation for JavaScript compression, reducing
25
+ # even more the file size.
26
+ # Sets the JavaScript reduce mode:
27
+ # "rake" - Reduce only when executing rake task (asset:compress:js)
28
+ # true - Reduce at runtime or when executing rake
29
+ # false - Don't reduce JavaScript's
30
+ js_reducer: false
31
+
32
+ development:
33
+ slight_asset:
34
+ <<: *slight_asset
35
+
36
+ test:
37
+ slight_asset:
38
+ <<: *slight_asset
39
+
40
+ production:
41
+ slight_asset:
42
+ <<: *slight_asset
@@ -0,0 +1,2 @@
1
+ require "slight_assets"
2
+ SlightAssets::Rails.init!
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slight_assets
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Marcelo Manzan
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-06-20 00:00:00 -03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: yui-compressor
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 55
30
+ segments:
31
+ - 0
32
+ - 9
33
+ - 6
34
+ version: 0.9.6
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: step-up
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - "="
44
+ - !ruby/object:Gem::Version
45
+ hash: 7
46
+ segments:
47
+ - 0
48
+ - 6
49
+ - 0
50
+ version: 0.6.0
51
+ type: :development
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: rspec
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ type: :development
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: mocha
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ type: :development
80
+ version_requirements: *id004
81
+ - !ruby/object:Gem::Dependency
82
+ name: closure-compiler
83
+ prerelease: false
84
+ requirement: &id005 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ hash: 3
90
+ segments:
91
+ - 0
92
+ version: "0"
93
+ type: :development
94
+ version_requirements: *id005
95
+ description: Optimize the assets of your Rails application without change any line of code.
96
+ email:
97
+ - manzan@gmail.com
98
+ executables: []
99
+
100
+ extensions: []
101
+
102
+ extra_rdoc_files: []
103
+
104
+ files:
105
+ - generators/slight_assets/slight_assets_generator.rb
106
+ - lib/slight_assets.rb
107
+ - lib/slight_assets/base.rb
108
+ - lib/slight_assets/js_reducer.rb
109
+ - lib/slight_assets/rails.rb
110
+ - lib/slight_assets/rake_tasks.rb
111
+ - lib/slight_assets/settings.rb
112
+ - lib/slight_assets/settings/default_config.yml
113
+ - lib/slight_assets/util.rb
114
+ - lib/slight_assets/version.rb
115
+ - templates/install/config/assets.yml
116
+ - templates/install/config/initializers/assets.rb
117
+ has_rdoc: true
118
+ homepage: https://github.com/kawamanza/slight_assets
119
+ licenses: []
120
+
121
+ post_install_message:
122
+ rdoc_options: []
123
+
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ hash: 3
132
+ segments:
133
+ - 0
134
+ version: "0"
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ hash: 23
141
+ segments:
142
+ - 1
143
+ - 3
144
+ - 6
145
+ version: 1.3.6
146
+ requirements: []
147
+
148
+ rubyforge_project: slight_assets
149
+ rubygems_version: 1.3.7
150
+ signing_key:
151
+ specification_version: 3
152
+ summary: All you need to make your rails application more fast.
153
+ test_files: []
154
+