slight_assets 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.
@@ -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
+