spritely 0.3.2 → 1.0.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.
- checksums.yaml +4 -4
- data/lib/spritely.rb +11 -34
- data/lib/spritely/collection.rb +12 -11
- data/lib/spritely/engine.rb +4 -0
- data/lib/spritely/generators/base.rb +0 -16
- data/lib/spritely/generators/chunky_png.rb +1 -4
- data/lib/spritely/image_set.rb +2 -2
- data/lib/spritely/sass_functions.rb +30 -29
- data/lib/spritely/sprite_map.rb +14 -31
- data/lib/spritely/sprockets/preprocessor.rb +65 -0
- data/lib/spritely/sprockets/transformer.rb +43 -0
- data/lib/spritely/version.rb +1 -1
- data/spec/fixtures/rails-app-changes/app/assets/stylesheets/sprites.css.scss +10 -18
- data/spec/fixtures/rails-app/app/assets/images/sprites/application.png.sprite +5 -0
- data/spec/fixtures/rails-app/app/assets/images/sprites/foo.png.sprite +1 -0
- data/spec/fixtures/rails-app/app/assets/stylesheets/sprites.css.scss +6 -14
- data/spec/fixtures/rails-app/app/assets/stylesheets/sprites_2.css.scss +4 -6
- data/spec/integration/precompilation_spec.rb +2 -14
- data/spec/spec_helper.rb +0 -4
- data/spec/spritely/collection_spec.rb +9 -8
- data/spec/spritely/generators/chunky_png_spec.rb +8 -13
- data/spec/spritely/image_set_spec.rb +2 -8
- data/spec/spritely/sass_functions_spec.rb +38 -37
- data/spec/spritely/sprite_map_spec.rb +16 -52
- data/spec/spritely/sprockets/preprocessor_spec.rb +33 -0
- data/spec/support/rails_app_helpers.rb +4 -5
- metadata +38 -49
- data/lib/generators/spritely/install_generator.rb +0 -17
- data/lib/spritely/adapters/sprockets_2.rb +0 -13
- data/lib/spritely/adapters/sprockets_3.rb +0 -11
- data/lib/spritely/cache.rb +0 -51
- data/lib/spritely/options.rb +0 -59
- data/lib/spritely/sprockets/manifest.rb +0 -20
- data/spec/generators/spritely/install_generator_spec.rb +0 -28
- data/spec/spritely/cache_spec.rb +0 -24
- data/spec/spritely/options_spec.rb +0 -29
- data/spec/spritely_spec.rb +0 -41
- data/spec/support/shared_examples.rb +0 -40
- data/spec/support/shared_examples/sprockets_2_sass_functions_helpers.rb +0 -13
- data/spec/support/shared_examples/sprockets_3_sass_functions_helpers.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1afa4634c2ebe161a2557ad31168f308f4fd4de
|
4
|
+
data.tar.gz: 176498f2a2579987e8c8ac4c12cc960e1ceba4b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95d85bb25e1761b8223f6fc2bc2aeb50a9e3c8f7cb91e15842b5f767d7b8545fe330dfdec6f39b9919107d82b83ccae1eee973863f15a47dbad28f74aae8d78a
|
7
|
+
data.tar.gz: 6709371eaedb1db506fa2ab023f197e978e477f0017a1100e3f2337663b64c86c32e39250109cd3b91fedfce315259dd060b14c045202051f6245fc3cf70ecc5
|
data/lib/spritely.rb
CHANGED
@@ -1,38 +1,15 @@
|
|
1
|
-
require '
|
2
|
-
require 'sprockets/rails/version'
|
3
|
-
require 'sprockets/railtie'
|
4
|
-
require 'sprockets/version'
|
1
|
+
require 'sprockets'
|
5
2
|
require 'spritely/sass_functions'
|
6
|
-
require 'spritely/sprockets/
|
7
|
-
require 'spritely/
|
8
|
-
require 'spritely/adapters/sprockets_3'
|
3
|
+
require 'spritely/sprockets/preprocessor'
|
4
|
+
require 'spritely/sprockets/transformer'
|
9
5
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
::Rails.application.assets || ::Sprockets::Railtie.build_environment(::Rails.application)
|
14
|
-
else
|
15
|
-
::Rails.application.assets
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.directory
|
20
|
-
::Rails.root.join(relative_folder_path)
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.relative_folder_path
|
24
|
-
Pathname.new(File.join('app', 'assets', 'images', 'sprites'))
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.sprockets_version
|
28
|
-
Gem::Version.new(::Sprockets::VERSION).segments.first
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.sprockets_rails_version
|
32
|
-
Gem::Version.new(::Sprockets::Rails::VERSION).segments.first
|
33
|
-
end
|
6
|
+
if defined?(::Rails::Engine)
|
7
|
+
require 'spritely/engine'
|
8
|
+
end
|
34
9
|
|
35
|
-
|
36
|
-
Adapters.const_get("Sprockets#{sprockets_version}").new
|
37
|
-
end
|
10
|
+
module Spritely
|
38
11
|
end
|
12
|
+
|
13
|
+
::Sprockets.register_mime_type 'text/sprite', extensions: ['.png.sprite']
|
14
|
+
::Sprockets.register_preprocessor 'text/sprite', Spritely::Sprockets::Preprocessor.new(comments: ["//", ["/*", "*/"]])
|
15
|
+
::Sprockets.register_transformer 'text/sprite', 'image/png', Spritely::Sprockets::Transformer
|
data/lib/spritely/collection.rb
CHANGED
@@ -21,6 +21,7 @@ module Spritely
|
|
21
21
|
def cache_key
|
22
22
|
files.collect { |file| Digest::MD5.file(file) }.join
|
23
23
|
end
|
24
|
+
alias_method :to_s, :cache_key
|
24
25
|
|
25
26
|
# Returns the width of the to-be-generated sprite image. When none of the
|
26
27
|
# images repeat, it is simply the max width of all images in the sprite.
|
@@ -29,17 +30,13 @@ module Spritely
|
|
29
30
|
# multiple is then multiplied by the minimum multiple that will result in a
|
30
31
|
# value greater than or equal to the max width of all images in the sprite.
|
31
32
|
def width
|
32
|
-
|
33
|
-
|
34
|
-
max_width = image_sets.collect(&:width).max
|
35
|
-
if image_sets.none?(&:repeated?)
|
36
|
-
@width = max_width
|
33
|
+
@width ||= if image_sets.none?(&:repeated?)
|
34
|
+
max_width
|
37
35
|
else
|
38
|
-
|
39
|
-
@width += lcm while @width < max_width
|
40
|
-
end
|
36
|
+
lcm = image_sets.select(&:repeated?).collect(&:width).reduce(:lcm)
|
41
37
|
|
42
|
-
|
38
|
+
lcm * (max_width / lcm.to_f).ceil
|
39
|
+
end
|
43
40
|
end
|
44
41
|
|
45
42
|
def height
|
@@ -58,11 +55,15 @@ module Spritely
|
|
58
55
|
private
|
59
56
|
|
60
57
|
def image_sets
|
61
|
-
@image_sets ||= files.collect { |file| ImageSet.new(file, options[File.basename(file, ".png")]) }
|
58
|
+
@image_sets ||= files.collect { |file| ImageSet.new(file, options[:images][File.basename(file, ".png")] || options[:global]) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def max_width
|
62
|
+
@max_width ||= image_sets.collect(&:width).max
|
62
63
|
end
|
63
64
|
|
64
65
|
def heights
|
65
|
-
image_sets.collect(&:outer_height)
|
66
|
+
@heights ||= image_sets.collect(&:outer_height)
|
66
67
|
end
|
67
68
|
end
|
68
69
|
end
|
@@ -1,25 +1,9 @@
|
|
1
1
|
module Spritely
|
2
2
|
module Generators
|
3
3
|
class Base < Struct.new(:sprite_map)
|
4
|
-
def self.create!(sprite_map)
|
5
|
-
new(sprite_map).tap do |generator|
|
6
|
-
generator.build!
|
7
|
-
generator.ensure_directory_exists!
|
8
|
-
generator.save!
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def ensure_directory_exists!
|
13
|
-
raise("'#{Spritely.relative_folder_path}' doesn't exist. Run `rails generate spritely:install`.") unless File.exist?(Spritely.directory)
|
14
|
-
end
|
15
|
-
|
16
4
|
def build!
|
17
5
|
raise NotImplementedError, "#{self.class} must implement #build!"
|
18
6
|
end
|
19
|
-
|
20
|
-
def save!
|
21
|
-
raise NotImplementedError, "#{self.class} must implement #save!"
|
22
|
-
end
|
23
7
|
end
|
24
8
|
end
|
25
9
|
end
|
@@ -9,11 +9,8 @@ module Spritely
|
|
9
9
|
png = ::ChunkyPNG::Image.from_blob(image.data)
|
10
10
|
canvas.replace!(png, image.left, image.top)
|
11
11
|
end
|
12
|
-
end
|
13
12
|
|
14
|
-
|
15
|
-
canvas.metadata['cache_key'] = sprite_map.cache_key
|
16
|
-
canvas.save(sprite_map.filename, :fast_rgba)
|
13
|
+
canvas.to_blob(:fast_rgba)
|
17
14
|
end
|
18
15
|
|
19
16
|
private
|
data/lib/spritely/image_set.rb
CHANGED
@@ -1,28 +1,17 @@
|
|
1
|
-
require '
|
1
|
+
require 'sass'
|
2
2
|
|
3
3
|
module Spritely
|
4
4
|
module SassFunctions
|
5
|
-
def
|
6
|
-
|
7
|
-
Spritely.sprockets_adapter.reset_cache!(sprockets_environment, sprite_map.filename)
|
8
|
-
sprockets_context.depend_on(Spritely.directory)
|
9
|
-
sprite_map.files.each do |file|
|
10
|
-
sprockets_context.depend_on(file)
|
11
|
-
sprockets_context.depend_on_asset(file)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
::Sass::Script::Functions.declare :spritely_map, [:glob], var_kwargs: true
|
5
|
+
def spritely_url(sprite_name)
|
6
|
+
sprockets_context.link_asset("sprites/#{sprite_name.value}.png")
|
17
7
|
|
18
|
-
|
19
|
-
asset_url(Sass::Script::String.new("sprites/#{sprite_map.name}.png"))
|
8
|
+
asset_url(Sass::Script::String.new("sprites/#{sprite_name.value}.png"))
|
20
9
|
end
|
21
10
|
|
22
|
-
::Sass::Script::Functions.declare :spritely_url, [:
|
11
|
+
::Sass::Script::Functions.declare :spritely_url, [:sprite_name]
|
23
12
|
|
24
|
-
def spritely_position(
|
25
|
-
image = find_image(
|
13
|
+
def spritely_position(sprite_name, image_name)
|
14
|
+
image = find_image(sprite_name, image_name)
|
26
15
|
|
27
16
|
x = Sass::Script::Number.new(-image.left, image.left == 0 ? [] : ['px'])
|
28
17
|
y = Sass::Script::Number.new(-image.top, image.top == 0 ? [] : ['px'])
|
@@ -30,35 +19,47 @@ module Spritely
|
|
30
19
|
Sass::Script::List.new([x, y], :space)
|
31
20
|
end
|
32
21
|
|
33
|
-
::Sass::Script::Functions.declare :spritely_position, [:
|
22
|
+
::Sass::Script::Functions.declare :spritely_position, [:sprite_name, :image_name]
|
34
23
|
|
35
|
-
def spritely_background(
|
36
|
-
Sass::Script::List.new([spritely_url(
|
24
|
+
def spritely_background(sprite_name, image_name)
|
25
|
+
Sass::Script::List.new([spritely_url(sprite_name), spritely_position(sprite_name, image_name)], :space)
|
37
26
|
end
|
38
27
|
|
39
|
-
::Sass::Script::Functions.declare :spritely_background, [:
|
28
|
+
::Sass::Script::Functions.declare :spritely_background, [:sprite_name, :image_name]
|
40
29
|
|
41
|
-
def spritely_width(
|
42
|
-
image = find_image(
|
30
|
+
def spritely_width(sprite_name, image_name)
|
31
|
+
image = find_image(sprite_name, image_name)
|
43
32
|
|
44
33
|
Sass::Script::Number.new(image.width, ['px'])
|
45
34
|
end
|
46
35
|
|
47
|
-
::Sass::Script::Functions.declare :spritely_width, [:
|
36
|
+
::Sass::Script::Functions.declare :spritely_width, [:sprite_name, :image_name]
|
48
37
|
|
49
|
-
def spritely_height(
|
50
|
-
image = find_image(
|
38
|
+
def spritely_height(sprite_name, image_name)
|
39
|
+
image = find_image(sprite_name, image_name)
|
51
40
|
|
52
41
|
Sass::Script::Number.new(image.height, ['px'])
|
53
42
|
end
|
54
43
|
|
55
|
-
::Sass::Script::Functions.declare :spritely_height, [:
|
44
|
+
::Sass::Script::Functions.declare :spritely_height, [:sprite_name, :image_name]
|
56
45
|
|
57
46
|
private
|
58
47
|
|
59
|
-
def find_image(
|
48
|
+
def find_image(sprite_name, image_name)
|
49
|
+
sprockets_context.link_asset("sprites/#{sprite_name.value}.png")
|
50
|
+
|
51
|
+
sprite_map = sprite_maps.fetch(sprite_name.value) do |name|
|
52
|
+
asset = sprockets_environment.find_asset("sprites/#{name}.png.sprite") || raise(Sass::SyntaxError, "No sprite map '#{name}' found.")
|
53
|
+
|
54
|
+
sprite_maps[name] = SpriteMap.new(name, sprockets_environment, asset.metadata[:sprite_directives])
|
55
|
+
end
|
56
|
+
|
60
57
|
sprite_map.find(image_name.value) || raise(Sass::SyntaxError, "No image '#{image_name.value}' found in sprite map '#{sprite_map.name}'.")
|
61
58
|
end
|
59
|
+
|
60
|
+
def sprite_maps
|
61
|
+
@sprite_maps ||= {}
|
62
|
+
end
|
62
63
|
end
|
63
64
|
end
|
64
65
|
|
data/lib/spritely/sprite_map.rb
CHANGED
@@ -1,58 +1,41 @@
|
|
1
1
|
require 'forwardable'
|
2
|
-
require '
|
3
|
-
require 'spritely/cache'
|
2
|
+
require 'digest/md5'
|
4
3
|
require 'spritely/collection'
|
5
4
|
require 'spritely/generators/chunky_png'
|
6
5
|
|
7
6
|
module Spritely
|
8
|
-
class SpriteMap
|
7
|
+
class SpriteMap
|
9
8
|
extend Forwardable
|
10
9
|
|
11
10
|
def_delegators :collection, :find, :width, :height, :images
|
12
11
|
|
13
|
-
attr_reader :glob, :options
|
12
|
+
attr_reader :name, :glob, :environment, :options
|
14
13
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
def initialize(name, environment, options)
|
15
|
+
@name = name
|
16
|
+
@glob = [name, "*.png"].join("/")
|
17
|
+
@environment = environment
|
18
|
+
@options = options
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
22
|
-
|
23
|
-
@options = Options.new(options)
|
21
|
+
def inspect
|
22
|
+
"#<Spritely::SpriteMap name=#{name} options=#{options}>"
|
24
23
|
end
|
25
24
|
|
26
25
|
def cache_key
|
27
|
-
@cache_key ||=
|
28
|
-
end
|
29
|
-
|
30
|
-
def inspect
|
31
|
-
"#<Spritely::SpriteMap name=#{name} options=#{options}>"
|
26
|
+
@cache_key ||= Digest::MD5.hexdigest([options, collection].join)
|
32
27
|
end
|
33
28
|
|
34
29
|
def collection
|
35
30
|
@collection ||= Collection.create(files, options)
|
36
31
|
end
|
37
32
|
|
38
|
-
def
|
39
|
-
Generators::ChunkyPng.
|
40
|
-
end
|
41
|
-
|
42
|
-
def name
|
43
|
-
glob.split('/')[0..-2].join('-')
|
44
|
-
end
|
45
|
-
|
46
|
-
def filename
|
47
|
-
Spritely.directory.join("#{name}.png")
|
48
|
-
end
|
49
|
-
|
50
|
-
def needs_generation?
|
51
|
-
!File.exist?(filename) || Cache.busted?(filename, cache_key)
|
33
|
+
def save!
|
34
|
+
Generators::ChunkyPng.new(self).build!
|
52
35
|
end
|
53
36
|
|
54
37
|
def files
|
55
|
-
|
38
|
+
environment.paths.flat_map { |path| Dir.glob(File.join(path, glob)) }.sort
|
56
39
|
end
|
57
40
|
end
|
58
41
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'sprockets/directive_processor'
|
2
|
+
|
3
|
+
module Spritely
|
4
|
+
module Sprockets
|
5
|
+
# Converts Sprockets directives from this:
|
6
|
+
#
|
7
|
+
# //= repeat arrow true
|
8
|
+
# //= spacing arrow 10
|
9
|
+
# //= position another-image right
|
10
|
+
# //= spacing 5
|
11
|
+
#
|
12
|
+
# To this:
|
13
|
+
#
|
14
|
+
# {
|
15
|
+
# global: { spacing: 5 },
|
16
|
+
# images: {
|
17
|
+
# 'arrow' => { repeat: 'true', spacing: '10' },
|
18
|
+
# 'another-image' => { position: 'right', spacing: '5' }
|
19
|
+
# }
|
20
|
+
# }
|
21
|
+
class Preprocessor < ::Sprockets::DirectiveProcessor
|
22
|
+
GLOBAL_DIRECTIVES = %w(position spacing).freeze
|
23
|
+
IMAGE_DIRECTIVES = %w(repeat position spacing).freeze
|
24
|
+
|
25
|
+
def _call(input)
|
26
|
+
@sprite_directives = { global: {}, images: {} }
|
27
|
+
|
28
|
+
super.tap do
|
29
|
+
merge_global_options!
|
30
|
+
|
31
|
+
input[:metadata][:sprite_directives] = @sprite_directives
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
(GLOBAL_DIRECTIVES + IMAGE_DIRECTIVES).uniq.each do |directive|
|
36
|
+
define_method("process_#{directive}_directive") do |image_or_value, value_or_nil = nil|
|
37
|
+
if value_or_nil
|
38
|
+
process_image_option(directive, image_or_value, value_or_nil)
|
39
|
+
else
|
40
|
+
process_global_option(directive, image_or_value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def process_image_option(directive, image, value)
|
48
|
+
@sprite_directives[:images][image] ||= {}
|
49
|
+
@sprite_directives[:images][image][directive.to_sym] = value
|
50
|
+
end
|
51
|
+
|
52
|
+
def process_global_option(directive, value)
|
53
|
+
raise ArgumentError, "'#{directive}' is not a valid global option" unless GLOBAL_DIRECTIVES.include?(directive)
|
54
|
+
|
55
|
+
@sprite_directives[:global][directive.to_sym] = value
|
56
|
+
end
|
57
|
+
|
58
|
+
def merge_global_options!
|
59
|
+
@sprite_directives[:images].each do |image, options|
|
60
|
+
options.merge!(@sprite_directives[:global]) { |key, left, right| left }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spritely/version'
|
2
|
+
require 'spritely/sprite_map'
|
3
|
+
|
4
|
+
module Spritely
|
5
|
+
module Sprockets
|
6
|
+
class Transformer < Struct.new(:input)
|
7
|
+
def self.call(input)
|
8
|
+
new(input).call
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.cache_key
|
12
|
+
@cache_key ||= "#{name}:#{Spritely::VERSION}".freeze
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
data = cache.fetch([self.class.cache_key, input[:name], sprite_map.cache_key]) do
|
17
|
+
sprite_map.files.each do |file|
|
18
|
+
context.depend_on(File.dirname(file))
|
19
|
+
context.link_asset(file)
|
20
|
+
end
|
21
|
+
|
22
|
+
sprite_map.save!
|
23
|
+
end
|
24
|
+
|
25
|
+
context.metadata.merge(data: data)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def context
|
31
|
+
@context ||= input[:environment].context_class.new(input)
|
32
|
+
end
|
33
|
+
|
34
|
+
def cache
|
35
|
+
@cache ||= input[:cache]
|
36
|
+
end
|
37
|
+
|
38
|
+
def sprite_map
|
39
|
+
@sprite_map ||= SpriteMap.new(input[:name].remove("sprites/"), input[:environment], input[:metadata][:sprite_directives])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|