dynamic-sprites 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/dynamic-sprites +54 -0
- data/dynamic-sprites.sass +42 -0
- data/lib/dynamic-sprites.rb +31 -0
- data/lib/dynamic-sprites/generator.rb +73 -0
- data/lib/dynamic-sprites/interface.rb +64 -0
- data/lib/dynamic-sprites/runner.rb +76 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4e66fb4237da83f5be891b1d055a33a7db84ed1e
|
4
|
+
data.tar.gz: accd4811e105cffdd89760e68b256fbd1e2e192c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6578afb03c296b402be255ce957df3fe68efe74e8bcd8a7e624279b6df5e69aef27fdaf28d549da7b12c15e16b5e257c530b591422c768f11083055e0fad32a0
|
7
|
+
data.tar.gz: 4bf1e72083d3b38223cc21b0877ff85c6d8dce45bf6809dd9a5d510817d4d3acd576c359f6aff14e556d9717fb5efe210496a5cdf0625831de4c86a19d1209a4
|
data/bin/dynamic-sprites
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path("../lib", File.dirname(__FILE__)) # add sprite factory library to load path
|
4
|
+
|
5
|
+
require 'dynamic-sprites'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
options = { layout: 'vertical', selector: 'img.sprite' }
|
9
|
+
op = OptionParser.new
|
10
|
+
op.banner = <<-eos
|
11
|
+
#{DynamicSprites::DESCRIPTION}
|
12
|
+
|
13
|
+
Usage: dynamic-sprites <command> [PATH] [options]
|
14
|
+
|
15
|
+
Available commands:
|
16
|
+
init: generates sass mixin, you can pass your own path as an option
|
17
|
+
generate: generates sprite, you must enter relative or absolute path to source images
|
18
|
+
|
19
|
+
eos
|
20
|
+
|
21
|
+
op.on("-h", "--help") do
|
22
|
+
puts op.to_s
|
23
|
+
exit!
|
24
|
+
end
|
25
|
+
|
26
|
+
op.on("-v", "--version") do
|
27
|
+
puts DynamicSprites::VERSION
|
28
|
+
exit!
|
29
|
+
end
|
30
|
+
|
31
|
+
layout_help = "specify layout orientation ( horizontal, vertical, packed )"
|
32
|
+
selector_help = "specify custom selector to use ( default: 'img.sprite' )"
|
33
|
+
output_help = "specify output location for generated image ( default: <sources folder>.png )"
|
34
|
+
|
35
|
+
op.on("--layout [ORIENTATION]", layout_help) {|value| options[:layout] = value }
|
36
|
+
op.on("--selector [SELECTOR]", selector_help) {|value| options[:selector] = value }
|
37
|
+
op.on("--output [PATH]", output_help) {|value| options[:output] = value }
|
38
|
+
op.on("--layout [ORIENTATION]", layout_help) {|value| options[:layout] = value }
|
39
|
+
|
40
|
+
begin
|
41
|
+
op.parse!(ARGV)
|
42
|
+
command = ARGV[0]
|
43
|
+
path = ARGV[1]
|
44
|
+
if command.nil?
|
45
|
+
raise "You must pass command (init, generate)\nUsage: dynamic-sprites <command> [PATH] [options]"
|
46
|
+
elsif command == 'generate' and path.nil?
|
47
|
+
raise "Generate command requires path to source images\nUsage: dynamic-sprites generate <PATH> [options]"
|
48
|
+
end
|
49
|
+
ARGV.clear
|
50
|
+
DynamicSprites.run!(command, path, options)
|
51
|
+
rescue Exception => ex
|
52
|
+
puts ex.message
|
53
|
+
exit!
|
54
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
// Generates sass code for responsive sprites.
|
2
|
+
//
|
3
|
+
// sprite_url - String containing url to sprite image.
|
4
|
+
// images - Collection of strings, which represents images from sprites, each of them will generate separate class. Order must be preserved as in sprite
|
5
|
+
// image_height - Percentage height of image within sprite, (100% / ($number_of_images - 1))
|
6
|
+
// width - Element width
|
7
|
+
// padding_bottom - Padding bottom replaces height in its functionality.
|
8
|
+
//
|
9
|
+
// Examples
|
10
|
+
//
|
11
|
+
// .social img
|
12
|
+
// dynamic-sprite('/images/social.png', ('facebook', 'linkedin'))
|
13
|
+
//
|
14
|
+
// Returns sass for element and it's subclasses, for each image in sprite respectively.
|
15
|
+
@mixin dynamic-sprite($sprite_url, $images: (), $image_height : 100%, $width: 100%, $padding_bottom: 100%)
|
16
|
+
padding-bottom: $padding_bottom
|
17
|
+
width: $width
|
18
|
+
height: 0
|
19
|
+
background-repeat: no-repeat
|
20
|
+
background-image: url($sprite_url)
|
21
|
+
background-size: 100%
|
22
|
+
|
23
|
+
@for $i from 1 through length($images)
|
24
|
+
$image: nth($images, $i)
|
25
|
+
|
26
|
+
&.#{$image}
|
27
|
+
background-position: 0 $image_height * ($i - 1)
|
28
|
+
|
29
|
+
// Generates sass code for horizontal responsive sprites, everything works similar to vertical version.
|
30
|
+
@mixin dynamic-sprite-horizontal($sprite_url, $images: (), $image_width : 100%, $width: 100%, $padding_bottom: 100%)
|
31
|
+
padding-bottom: $padding_bottom
|
32
|
+
width: $width
|
33
|
+
height: 0
|
34
|
+
background-repeat: no-repeat
|
35
|
+
background-image: url($sprite_url)
|
36
|
+
background-size: 100% * length($images)
|
37
|
+
|
38
|
+
@for $i from 1 through length($images)
|
39
|
+
$image: nth($images, $i)
|
40
|
+
|
41
|
+
&.#{$image}
|
42
|
+
background-position: $image_width * ($i - 1) 0
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module DynamicSprites
|
2
|
+
|
3
|
+
#----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
VERSION = "0.0.2"
|
6
|
+
SUMMARY = "Dynamic sprites mixin in SASS with sprite generator"
|
7
|
+
DESCRIPTION = "Generates sass mixin and combines directory of images into one sprite"
|
8
|
+
|
9
|
+
require 'find'
|
10
|
+
require 'rmagick'
|
11
|
+
|
12
|
+
require_relative 'dynamic-sprites/runner' # Controller of this module
|
13
|
+
require_relative 'dynamic-sprites/interface' # User interaction methods
|
14
|
+
require_relative 'dynamic-sprites/generator' # Sprite generator
|
15
|
+
|
16
|
+
# Initilizes Runner which controls all the magic stuff.
|
17
|
+
#
|
18
|
+
def self.run!(command, path, options = {})
|
19
|
+
Runner.new(command, path, options).run!
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def self.gem_root
|
25
|
+
File.expand_path '../..', __FILE__
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.mixin_source_path
|
29
|
+
File.join gem_root, 'dynamic-sprites.sass'
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module DynamicSprites
|
2
|
+
# Generates sprites
|
3
|
+
class Generator
|
4
|
+
|
5
|
+
# Array of file extensions used for creating sprites.
|
6
|
+
#
|
7
|
+
VALID_EXTENSIONS = %w(.png .jpg .jpeg .gif .ico)
|
8
|
+
|
9
|
+
attr :filename
|
10
|
+
attr :layout
|
11
|
+
attr :files
|
12
|
+
|
13
|
+
# Initializer
|
14
|
+
#
|
15
|
+
# filename - Pathname where generated file should be placed to.
|
16
|
+
# path - Pathname of directory containing source images.
|
17
|
+
# layout - sprite layout name as a String
|
18
|
+
#
|
19
|
+
def initialize(filename, path, layout)
|
20
|
+
@filename = filename
|
21
|
+
@layout = layout
|
22
|
+
@files = Dir.glob(File.join(path, '*')).select { |e| VALID_EXTENSIONS.include?(File.extname(e)) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Main method for sprites generation
|
26
|
+
#
|
27
|
+
def run!
|
28
|
+
create(filename, load(files), layout)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# Converts Array of Filenames into an Array of Magic::Image objects
|
34
|
+
#
|
35
|
+
def load(files)
|
36
|
+
files.map do |filename|
|
37
|
+
image = Magick::Image.read(filename)[0]
|
38
|
+
{
|
39
|
+
:image => image,
|
40
|
+
:width => image.columns,
|
41
|
+
:height => image.rows
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Generates sprite
|
47
|
+
#
|
48
|
+
def create(filename, images, layout)
|
49
|
+
images_width = images.map{ |i| i[:width] }
|
50
|
+
images_height = images.map{ |i| i[:height] }
|
51
|
+
if layout == 'horizontal'
|
52
|
+
width = images_width.reduce(:+)
|
53
|
+
height = images_height.max
|
54
|
+
else
|
55
|
+
height = images_height.reduce(:+)
|
56
|
+
width = images_width.max
|
57
|
+
end
|
58
|
+
target = Magick::Image.new(width, height)
|
59
|
+
target.opacity = Magick::MaxRGB
|
60
|
+
offset_x = 0
|
61
|
+
offset_y = 0
|
62
|
+
images.each do |image|
|
63
|
+
target.composite!(image[:image], offset_x, offset_y, Magick::SrcOverCompositeOp)
|
64
|
+
if layout == 'horizontal'
|
65
|
+
offset_x += image[:width]
|
66
|
+
else
|
67
|
+
offset_y += image[:height]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
target.write(filename)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module DynamicSprites
|
2
|
+
# User Interaction class
|
3
|
+
#
|
4
|
+
class Interface
|
5
|
+
|
6
|
+
def prompt_directory
|
7
|
+
puts "Where should sass mixin be placed? (e.g. '/home/User/project/app/assets/stylesheets')"
|
8
|
+
prompt
|
9
|
+
end
|
10
|
+
|
11
|
+
def choose_directory(directories)
|
12
|
+
puts "Found more than one possible sass directory. To which one you want to insert sass mixin?"
|
13
|
+
option_number = 1
|
14
|
+
directories.each do |directory|
|
15
|
+
puts "#{option_number}. #{directory}"
|
16
|
+
option_number += 1
|
17
|
+
end
|
18
|
+
puts "#{option_number}. Other"
|
19
|
+
choice = choose(option_number)
|
20
|
+
if choice == option_number
|
21
|
+
puts "Enter directory path: (e.g. '/home/User/project/app/assets/stylesheets')"
|
22
|
+
prompt
|
23
|
+
else
|
24
|
+
directories[choice.to_i - 1]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def generate_mixin_summary(path)
|
29
|
+
puts "Mixin generated in #{path}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_sprite_summary(path)
|
33
|
+
puts "Sprite generated in #{path}"
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Choose option by it's index
|
39
|
+
#
|
40
|
+
def choose(limit)
|
41
|
+
puts "Select an option (1-#{limit}):"
|
42
|
+
choice = gets.to_i
|
43
|
+
raise RangeError unless choice.between?(1, limit)
|
44
|
+
choice
|
45
|
+
rescue RangeError
|
46
|
+
puts "Choose correct option (e.g. 1):"
|
47
|
+
retry
|
48
|
+
end
|
49
|
+
|
50
|
+
# Prompt user for specific Pathname
|
51
|
+
#
|
52
|
+
def prompt
|
53
|
+
path = gets
|
54
|
+
raise FileNotFoundError unless File.exist?(path)
|
55
|
+
Pathname.new(path)
|
56
|
+
rescue FileNotFoundError
|
57
|
+
puts "This path does not exist, try again:"
|
58
|
+
retry
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class FileNotFoundError < StandardError
|
64
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module DynamicSprites
|
2
|
+
class Runner
|
3
|
+
|
4
|
+
attr :command
|
5
|
+
attr :path
|
6
|
+
attr :options
|
7
|
+
attr :interface
|
8
|
+
|
9
|
+
def initialize(command, path, options = {})
|
10
|
+
@interface = Interface.new
|
11
|
+
@command = command
|
12
|
+
@path = Pathname.new(path) unless path.nil?
|
13
|
+
@path ||= File.join(sass_directory, 'dynamic-sprites.sass') unless command.nil?
|
14
|
+
@options = options
|
15
|
+
@options[:output] ||= "#{@path}.png"
|
16
|
+
end
|
17
|
+
|
18
|
+
# Runs dynamic-sprites command.
|
19
|
+
#
|
20
|
+
def run!
|
21
|
+
case command
|
22
|
+
when 'init'
|
23
|
+
generate_mixin!
|
24
|
+
when 'generate'
|
25
|
+
generate_sprite!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Generates mixin in provided path or initializes user interface to determine it otherwise.
|
32
|
+
#
|
33
|
+
def generate_mixin!
|
34
|
+
FileUtils.copy DynamicSprites.mixin_source_path, path
|
35
|
+
interface.generate_mixin_summary(path)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Generates sprite using provided options.
|
39
|
+
#
|
40
|
+
def generate_sprite!
|
41
|
+
Generator.new(options[:output], path, options[:layout]).run!
|
42
|
+
interface.generate_sprite_summary(@options[:output])
|
43
|
+
end
|
44
|
+
|
45
|
+
# Chooses one of possible options of defining sass directory path.
|
46
|
+
#
|
47
|
+
def sass_directory
|
48
|
+
case sass_directories.size
|
49
|
+
when 0
|
50
|
+
interface.prompt_directory
|
51
|
+
when 1
|
52
|
+
sass_directories.first
|
53
|
+
else
|
54
|
+
interface.choose_directory(sass_directories)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns an Array of possible paths to directories of project .sass files.
|
59
|
+
#
|
60
|
+
def sass_directories
|
61
|
+
style_directories = []
|
62
|
+
|
63
|
+
Find.find(Dir.pwd) do |path|
|
64
|
+
next unless FileTest.directory?(path)
|
65
|
+
if File.basename(path).match /sass|style/
|
66
|
+
style_directories << Pathname.new(path)
|
67
|
+
elsif File.basename(path)[0] == ?.
|
68
|
+
Find.prune
|
69
|
+
else
|
70
|
+
next
|
71
|
+
end
|
72
|
+
end
|
73
|
+
style_directories
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dynamic-sprites
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maciej Walusiak
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-05 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Dynamic sprites mixin in SASS with sprite generator.
|
14
|
+
email: rabsztok@gmail.com
|
15
|
+
executables:
|
16
|
+
- dynamic-sprites
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/dynamic-sprites.rb
|
21
|
+
- lib/dynamic-sprites/runner.rb
|
22
|
+
- lib/dynamic-sprites/generator.rb
|
23
|
+
- lib/dynamic-sprites/interface.rb
|
24
|
+
- dynamic-sprites.sass
|
25
|
+
- bin/dynamic-sprites
|
26
|
+
homepage: https://github.com/Rabsztok/dynamic-sprites
|
27
|
+
licenses:
|
28
|
+
- GPL
|
29
|
+
metadata: {}
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubyforge_project:
|
46
|
+
rubygems_version: 2.0.7
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: Dynamic sprites
|
50
|
+
test_files: []
|
51
|
+
has_rdoc:
|