Skip to content

Commit 87f2281

Browse files
committed
Introducing proxies and re-introducing image manipulation.
Fixes #160: Use {% img name.ext magick:crop:value %} Fixes #149: Use {% img name.ext magick:2x %} also 4x, half. Insur #159: Use a hash of the proxies for the image path. Fixes #150: Simply because the new syntax is solidified. This patch introduces the concept of proxies, so that tags can have proxies that manipulate data, the base included proxy is a magick filter that allows you to adjust and manipulate your image but any number of filters can be used. Because an image can be filtered any number of times each proxy that changes an image will trigger a new hash resulting in an entirely uniq image but if you use an image with a filter 20 times it should in theory continue to cache it and only run the proxies once and hold that cache until you either change the proxy attributes or clear the cache.
1 parent 584cc06 commit 87f2281

19 files changed

+507
-187
lines changed

.rspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
--color --fail-fast
1+
--color

README.md

-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ the ground rules for our tags as a specification.
8282
* `magick:2x` - Tells us to write a double width/height image.
8383
* `magick:4x` - Tells us to write a quadruple width/height image.
8484
* `magick:half` - Tells us to shrink the image to half.
85-
* `magick:quality` - Allows you to set image quality.
8685

8786
## Hooks
8887

lib/jekyll/assets.rb

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
require_relative "assets/helpers"
2-
require_relative "assets/hook"
31
require "sprockets"
42
require "sprockets/helpers"
53
require "jekyll"
64

75
require_relative "assets/hook"
8-
Dir[File.expand_path("../assets/extras/*.rb", __FILE__)].each do |f|
9-
require f
10-
end
6+
require_relative "assets/helpers"
7+
require_relative "assets/extras/es6"
8+
require_relative "assets/extras/helpers"
9+
require_relative "assets/extras/prefix"
1110

1211
require_relative "assets/env"
13-
require_relative "assets/whitelist"
1412
require_relative "assets/patches/jekyll/cleaner"
13+
require_relative "assets/patches/sprockets/asset"
1514
require_relative "assets/patches/jekyll/site"
1615

1716
require_relative "assets/hooks/post_read"

lib/jekyll/assets/cached.rb

+2-10
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,10 @@
11
module Jekyll
22
module Assets
3-
4-
# Creates:
5-
# * `#parent` - Leading back to the original Jekyll::Assets::Env instance.
6-
# * `#jekyll` - Leading back to the `Jekyll::Site` instance.
7-
#
8-
# The reason we add these is because sometimes we might need access to
9-
# the configuration or even to find another asset tied to a cached asset
10-
# so we can verify, find... etc, etc, etc.
11-
123
class Cached < Sprockets::CachedEnvironment
134
attr_reader :jekyll, :parent
145
def initialize(env)
15-
@parent, @jekyll = env, env.jekyll
6+
@parent = env
7+
@jekyll = env.jekyll
168
super env
179
end
1810
end

lib/jekyll/assets/configuration.rb

+10-13
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,19 @@ module Configuration
2727
},
2828
})
2929

30-
# Merges the users configuration with the default configuration so
31-
# that there is always some form of stable configuration for you to tap
32-
# into. This is merged into `#asset_config`.
30+
def self.defaults
31+
%W(development test).include?(Jekyll.env) ? DEVELOPMENT : PRODUCTION
32+
end
3333

34-
def self.merge(merge_into, config = nil)
35-
config ||= %(development test).include?(Jekyll.env) ? DEVELOPMENT : PRODUCTION
34+
def self.merge(merge_into, config = self.defaults)
3635
merge_into = merge_into.dup
36+
config.each_with_object(merge_into) do |(k, v), h|
37+
if !h.has_key?(k) || (v.is_a?(Hash) && !h[k])
38+
h[k] = v
3739

38-
config.each_with_object(merge_into) do |(key, value), hash|
39-
if !hash.has_key?(key) || (value.is_a?(Hash) && !hash[key])
40-
hash[key] = \
41-
value
42-
43-
elsif value.is_a?(Hash)
44-
hash[key] = merge hash[key], \
45-
value
40+
elsif v.is_a?(Hash)
41+
h[k] = merge h[k], \
42+
v
4643
end
4744
end
4845

lib/jekyll/assets/context.rb

+2-4
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ def patch(what)
99
what.class_eval do
1010
alias_method :_old_asset_path, :asset_path
1111
def asset_path(asset, opts = {})
12-
out = _old_asset_path asset, opts = {}
13-
unless out
14-
return
15-
end
12+
out = _old_asset_path asset
13+
return unless out
1614

1715
environment.parent.used.add(environment.find_asset \
1816
resolve(asset))

lib/jekyll/assets/env.rb

+27-45
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ def initialize(path, jekyll = nil)
2727
jekyll.sprockets = self
2828
end
2929

30+
def in_cache_dir(*paths)
31+
cache_dir = asset_config.fetch("cache", ".asset-cache") || nil
32+
jekyll.in_source_dir(
33+
cache_dir, *paths
34+
)
35+
end
36+
3037
def cached_write?
3138
!@used.any?
3239
end
@@ -57,60 +64,25 @@ def prefix_path(path = nil)
5764
return File.join(cdn, prefix) if !path
5865
File.join(cdn, prefix, path)
5966
else
60-
return prefix if !path
61-
File.join(
62-
prefix, path
63-
)
67+
return prefix if !path
68+
File.join(prefix, path)
6469
end
6570
end
6671

67-
# See: `Cached`
68-
6972
def cached
7073
Cached.new(self)
7174
end
7275

73-
# See: `write_cached_assets`
74-
# See: `write_assets`
75-
7676
def write_all
7777
if cached_write?
7878
then write_cached_assets else write_assets
7979
end
8080
end
8181

82-
# Merge the defaults with your configuration so that there is always
83-
# some state and so that there need not be any configuration provided
84-
# by the user, this allows you to just accept our defaults while
85-
# changing only the things that you want changed.
86-
87-
private
88-
def merge_config(config = nil, merge_into = asset_config)
89-
config ||= dev?? Configuration::DEVELOPMENT : Configuration::PRODUCTION
90-
config.each_with_object(merge_into) do |(k, v), h|
91-
if !h.has_key?(k)
92-
h[k] = \
93-
v
94-
95-
elsif v.is_a?(Hash)
96-
h[k] = merge_config(
97-
v, h[k]
98-
)
99-
end
100-
end
101-
102-
103-
merge_into
104-
end
105-
106-
# If we have used assets then we are working with a brand new
107-
# build and a brand new set of assets, so we reset the asset_cache
108-
# and digest_cache and write everything fresh from the start.
109-
11082
private
111-
def write_assets(assets = self.all_used_assets)
112-
self.class.assets_cache = Set.new(assets)
113-
self.class.digest_cache = Hash[Set.new(assets).map do |a|
83+
def write_assets(assets = self.all_assets)
84+
self.class.assets_cache = assets
85+
self.class.digest_cache = Hash[assets.map do |a|
11486
[a.logical_path, a.digest]
11587
end]
11688

@@ -120,11 +92,21 @@ def write_assets(assets = self.all_used_assets)
12092
end
12193

12294
private
123-
def write_cached_assets
124-
all_assets(true).each do |a|
125-
viejo = self.class.digest_cache[a.logical_path]
126-
nuevo = find_asset(a.logical_path).digest
127-
next if nuevo == viejo
95+
def write_cached_assets(assets = all_assets(true))
96+
assets.each do |a|
97+
if !a.is_a?(Tag::ProxiedAsset)
98+
viejo = self.class.digest_cache[a.logical_path]
99+
nuevo = find_asset(a.logical_path).digest
100+
path = as_path a
101+
102+
if nuevo == viejo && File.file?(path)
103+
next
104+
end
105+
else
106+
if File.file?(a.logical_path)
107+
next
108+
end
109+
end
128110

129111
self.class.digest_cache[a.logical_path] = a.digest
130112
a.write_to as_path a
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module Sprockets
2+
class Asset
3+
def data_uri
4+
"data:#{content_type};base64,#{Rack::Utils.escape \
5+
Base64.encode64(to_s)}"
6+
end
7+
8+
def liquid_tags
9+
metadata[:liquid_tags] ||= \
10+
Set.new
11+
end
12+
end
13+
end

lib/jekyll/assets/tag.rb

+21-14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
module Jekyll
22
module Assets
3+
4+
# TODO: Somewhere in here we need to designate the proxy as an asset
5+
# so that the env does not need to be aware of anything.
6+
37
class Tag < Liquid::Tag
8+
require_relative "tag/proxied_asset"
49
require_relative "tag/parser"
10+
attr_reader :args
511

612
class AssetNotFoundError < StandardError
713
def initialize(asset)
@@ -23,8 +29,10 @@ def initialize(asset)
2329
}
2430

2531
def initialize(tag, args, tokens)
26-
@tokens, @tag, @og_tag, @url_options = tokens, from_alias(tag), tag, {}
32+
@tokens = tokens
33+
@tag = from_alias(tag)
2734
@args = Parser.new(args, @tag)
35+
@og_tag = tag
2836
super
2937
end
3038

@@ -63,7 +71,7 @@ def process_tag(sprockets, asset)
6371

6472
elsif @args[:data][:uri]
6573
return TAGS[@tag] % [
66-
data_uri(asset), @args.to_html
74+
asset.data_uri, @args.to_html
6775
]
6876

6977
else
@@ -76,8 +84,9 @@ def process_tag(sprockets, asset)
7684

7785
private
7886
def get_path(sprockets, asset)
79-
asset_path = sprockets.digest?? asset.digest_path : asset.logical_path
80-
sprockets.prefix_path(asset_path)
87+
sprockets.prefix_path(
88+
sprockets.digest?? asset.digest_path : asset.logical_path
89+
)
8190
end
8291

8392
private
@@ -87,12 +96,6 @@ def set_img_alt(asset)
8796
end
8897
end
8998

90-
private
91-
def data_uri(asset)
92-
data = Rack::Utils.escape(Base64.encode64(asset.to_s))
93-
"data:#{asset.content_type};base64,#{data}"
94-
end
95-
9699
private
97100
def add_as_jekyll_dependency(site, sprockets, page, asset)
98101
if page && sprockets.digest?
@@ -105,11 +108,15 @@ def add_as_jekyll_dependency(site, sprockets, page, asset)
105108
private
106109
def find_asset(sprockets)
107110
if !(out = sprockets.find_asset(@args[:file], @args[:sprockets]))
108-
raise AssetNotFoundError, @args[:file] else out.metadata[:tag] = \
109-
@args
111+
raise AssetNotFoundError, @args[:file]
112+
else
113+
out.liquid_tags << self
114+
if !@args.has_proxies?
115+
out else ProxiedAsset.new(
116+
out, @args, sprockets, self
117+
)
118+
end
110119
end
111-
112-
out
113120
end
114121

115122
# There is no guarantee that Jekyll will pass on the error for

0 commit comments

Comments
 (0)