Added pre-deploy sprite generator

Sprite generator now with less suck
This commit is contained in:
Joel Junström
2012-02-21 14:29:39 +01:00
parent 69e1e951ba
commit a39d26af66
5 changed files with 248 additions and 118 deletions
+1
View File
@@ -2,3 +2,4 @@ source :rubygems
gem 'fog'
gem 'mime-types'
gem 'rake'
gem 'nokogiri'
+1
View File
@@ -29,4 +29,5 @@ PLATFORMS
DEPENDENCIES
fog
mime-types
nokogiri
rake
+4 -118
View File
@@ -1,125 +1,11 @@
require 'rubygems'
require 'bundler'
Bundler.require
require 'digest/sha1'
require_relative 'lib/simple_s3_deploy'
require_relative 'lib/emoji_optimizer'
task :deploy do
SimpleS3Deploy.deploy('public')
end
module SimpleS3Deploy
def self.deploy(site_path)
Site.new(site_path).deploy
EmojiOptimizer.new(:size => 22, :padding => 5).optimize! do
SimpleS3Deploy.deploy('public')
end
class Site
attr_accessor :path
attr_accessor :tmp_files
def initialize(path)
@path = path
@tmp_files = []
end
def deploy
puts " ** Deploying #{path} to #{bucket.key}"
puts " ========================================================"
puts " ** Deleting existing remote files"
clear_bucket
puts " ** Uploading files"
files.each do |file|
if !File.directory?(file.path)
remote_file_name = file_base_path(file.path)
puts " Uploading #{remote_file_name} .."
bucket.files.create(
key: remote_file_name,
body: file.is_minifyable? ? open(minify(file.path)) : open(file.path),
public: true,
content_type: file.mime_type,
cache_control: 'max-age=604800, public' )
end
end
if tmp_files.any?
puts " ** Cleaning up tmp files"
cleanup
end
puts "\n ** Done"
end
private
def clear_bucket
bucket.files.each do |f|
puts " Deleting #{f.key}"
f.destroy
end
end
def cleanup
tmp_files.each do |file|
puts " Deleting #{file}"
File.unlink(file)
end
end
def files
@files ||= Dir.glob("#{path}/**/*").map { |f| SiteFile.new(f) }
end
def file_base_path(file)
file.gsub("#{path}/", "")
end
def minify(file_path)
"#{file_path}-tmp".tap do |tmp_file_name|
`yuicompressor -o #{tmp_file_name} #{file_path}`
tmp_files << tmp_file_name
end
end
def config
@config ||= YAML.load_file('config.yaml')
end
def s3
@s3 ||= Fog::Storage.new({
provider: 'AWS',
aws_secret_access_key: config['s3']['secret_access_key'],
aws_access_key_id: config['s3']['access_key_id'] })
end
def bucket
@bucket ||= s3.directories.get(config['s3']['bucket'])
end
end
class SiteFile
attr_accessor :path
def initialize(_path)
@path = _path
end
def is_minifyable?
is_css_file? or is_js_file?
end
def is_css_file?
path.end_with?('.css')
end
def is_js_file?
path.end_with?('.js')
end
def mime_type
MIME::Types.type_for(path)[0].to_s
end
end
end
+128
View File
@@ -0,0 +1,128 @@
require 'digest/md5'
require 'tmpdir'
class EmojiOptimizer
def initialize(options = {})
@size = options.delete(:size) { 22 }
@padding = options.delete(:padding) { 5 }
@source = Source.new('public/index.html')
end
def optimize!(&block)
puts " ** Preparing for optimization"
prepare
puts " ** Generating emoji sprite image"
if @source.create_sprite(@size, @padding, sprite_path)
puts " ** Generating css and updating markup"
generate_and_save
else
puts " ** Could not generate emoji sprite =("
end
yield
ensure
puts " ** Cleaning up after optimization"
cleanup
end
private
def prepare
FileUtils.cp 'public/index.html', File.join(tmp_dir, 'index.html')
FileUtils.cp 'public/emoji.css', File.join(tmp_dir, 'emoji.css')
end
def generate_and_save
update_source_markup
File.open('public/emoji.css', 'a') { |f| f.puts css_rules.join("\n") }
File.open('public/index.html','w') { |f| f.write @source.to_html }
FileUtils.mv sprite_path, "public/graphics/#{digest_name}"
end
def cleanup
FileUtils.mv File.join(tmp_dir, 'index.html'), 'public/index.html'
FileUtils.mv File.join(tmp_dir, 'emoji.css'), 'public/emoji.css'
FileUtils.rm_f "public/graphics/#{@digest_name}"
end
def css_rules
[].tap do |rules|
rules << %Q{
.emoji {
display:inline-block;
width:#{@size}px;
height:#{@size}px;
background:transparent url(/graphics/#{digest_name}) 0 0 no-repeat;
}
}
@source.emojis.size.times do |index|
rules << css_sprite_mapping(index)
end
end
end
def update_source_markup
@source.emojis.each_with_index do |img, index|
img.replace @source.create_element('span', {
'id' => "e_#{index+1}",
'class' => 'emoji',
'data-src' => img['src']
})
end
end
def css_sprite_mapping(index)
offset = ((@size + @padding * 2) * index) + @padding
"#e_#{index+1} { background-position:-#{offset}px 0; }"
end
def sprite_path
@sprite_path ||= File.join(tmp_dir, 'sprite.png')
end
def digest_name
@digest_name ||= "sprite_#{Digest::MD5.hexdigest(File.read(sprite_path))}.png"
end
def tmp_dir
@tmp_dir ||= Dir.mktmpdir 'emoji-optimization'
end
class Source
def initialize(file)
@file = file
end
def emojis
@emojis ||= doc.css('#content img').find_all { |img| img['src'] =~ /emojis/ }
end
def emoji_paths
@emoji_paths ||= emojis.map { |img| File.join('public', img['src']) }
end
def create_sprite(size, padding, path)
system "montage #{emoji_paths.join(' ')} -tile x1 -geometry #{size}x#{size}+#{padding} -background transparent #{path}"
end
def create_element(*args)
doc.create_element *args
end
def to_html
doc.to_html
end
private
def doc
@doc ||= Nokogiri::HTML(File.open(@file))
end
end
end
+114
View File
@@ -0,0 +1,114 @@
module SimpleS3Deploy
def self.deploy(site_path)
Site.new(site_path).deploy
end
class Site
attr_accessor :path
attr_accessor :tmp_files
def initialize(path)
@path = path
@tmp_files = []
end
def deploy
puts " ** Deploying #{path} to #{bucket.key}"
puts " ========================================================"
puts " ** Deleting existing remote files"
clear_bucket
puts " ** Uploading files"
files.each do |file|
if !File.directory?(file.path)
remote_file_name = file_base_path(file.path)
puts " Uploading #{remote_file_name} .."
bucket.files.create(
key: remote_file_name,
body: file.is_minifyable? ? open(minify(file.path)) : open(file.path),
public: true,
content_type: file.mime_type,
cache_control: 'max-age=604800, public' )
end
end
if tmp_files.any?
puts " ** Cleaning up tmp files"
cleanup
end
puts "\n ** Done"
end
private
def clear_bucket
bucket.files.each do |f|
puts " Deleting #{f.key}"
f.destroy
end
end
def cleanup
tmp_files.each do |file|
puts " Deleting #{file}"
File.unlink(file)
end
end
def files
@files ||= Dir.glob("#{path}/**/*").map { |f| SiteFile.new(f) }
end
def file_base_path(file)
file.gsub("#{path}/", "")
end
def minify(file_path)
"#{file_path}-tmp".tap do |tmp_file_name|
`yuicompressor -o #{tmp_file_name} #{file_path}`
tmp_files << tmp_file_name
end
end
def config
@config ||= YAML.load_file('config.yaml')
end
def s3
@s3 ||= Fog::Storage.new({
provider: 'AWS',
aws_secret_access_key: config['s3']['secret_access_key'],
aws_access_key_id: config['s3']['access_key_id'] })
end
def bucket
@bucket ||= s3.directories.get(config['s3']['bucket'])
end
end
class SiteFile
attr_accessor :path
def initialize(_path)
@path = _path
end
def is_minifyable?
is_css_file? or is_js_file?
end
def is_css_file?
path.end_with?('.css')
end
def is_js_file?
path.end_with?('.js')
end
def mime_type
MIME::Types.type_for(path)[0].to_s
end
end
end