jekyll-images 0.2.5 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ade8806597db4aad25430a39bb1c7a8db08e4e474015344e7afe2e8bbd717038
4
- data.tar.gz: c97d3622656034a395f745aaeafe47fc994cb1c1a18ba9853251ef77f924ebcc
3
+ metadata.gz: 940d7564e5f46ba24c22eec51f474252fc5f23445f37f2589a05788c2b107e55
4
+ data.tar.gz: 3fdb9012e009324edac12a65d2550dedb93cb4bf899d50ce011a0849c23fc44a
5
5
  SHA512:
6
- metadata.gz: 3398cc500da4c3ee7ea3be463247422636e37d9a363ab5b2aa94a42acd755f90341995c35b51055fe6bb446b90526a383d3bffbb507cbde64750b98cb85ac94c
7
- data.tar.gz: b76bdd36d899533d031990eb152bb93032e609877b32806b9a629c6c4590ddef5baae6e63e8f98a236574d3a21d0fb10538c64ac8d7fee7b64e92af55418c1a6
6
+ metadata.gz: f1b872ea8903b49b10efe560c0d568debcdfb937a8efbdb6059f238251ab71279d78056479d756cbc7c6bef34577e23c09e22c0ce97ff73d1e2ec0e853b31a49
7
+ data.tar.gz: 59136867e0841097770b5ae7f3a774f8a4d6934445dcc0bf8e47ab6df4104bd70d34061eb88ac0bcf0c7ef6c53a4b30c970f959164700a41cb4a501008593772
data/README.md CHANGED
@@ -53,10 +53,12 @@ In your templates, you can use the `thumbnail` filter:
53
53
 
54
54
  Options for this filter are in the following order:
55
55
 
56
- * `width` (required), the desired width for the image
56
+ * `width`, the desired width for the image, if `nil`, `height` is
57
+ required.
57
58
 
58
59
  * `height`, if provided, the thumbnail will crop to this size. If not,
59
- the image is scaled down proportionally to the width.
60
+ the image is scaled down proportionally to the width. It becomes
61
+ required if the width is `nil`.
60
62
 
61
63
  * `crop` the smart cropping algorithm. One of `none`, `centre`,
62
64
  `entropy` or `attention` (default). See
@@ -67,7 +69,7 @@ Options for this filter are in the following order:
67
69
  orientation metadata, this controls if it's automatically rotated.
68
70
 
69
71
  If you want to pass `crop` and `auto_rotate` but not `height`, just set
70
- `height` to `0` or `''`.
72
+ `height` to `nil`.
71
73
 
72
74
  ## TODO
73
75
 
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Filters
5
+ # Obtain image height
6
+ module Height
7
+ def height(input)
8
+ return unless input
9
+ input = @context.registers[:site].in_source_dir input
10
+
11
+ unless ::File.exist? input
12
+ Jekyll.logger.warn "File doesn't exist #{input}"
13
+ return input
14
+ end
15
+
16
+ Jekyll::Images::Cache.cached_image(input).height
17
+ rescue Vips::Error => e
18
+ Jekyll.logger.warn "Failed to process #{input}: #{e.message}"
19
+ nil
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ Liquid::Template.register_filter(Jekyll::Filters::Height)
@@ -1,41 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pry'
4
3
  module Jekyll
5
4
  module Filters
6
5
  # Liquid filter for use in templates
7
6
  module Thumbnail
8
- @@cached_images = {}
9
-
10
7
  # Generates a thumbnail and returns its alternate destination
11
- def thumbnail(input, width, height = nil, crop = :attention, auto_rotate = true)
8
+ def thumbnail(input, width = nil, height = nil, crop = nil, auto_rotate = nil)
12
9
  return unless input
13
- return cached_image(input).dest if cached_image? input
10
+ input = @context.registers[:site].in_source_dir input
11
+
12
+ unless ::File.exist? input
13
+ Jekyll.logger.warn "File doesn't exist #{input}"
14
+ return input
15
+ end
14
16
 
15
- height = height if height.to_i > 1
16
- image = cached_image input, width, height, crop, auto_rotate
17
+ image = Jekyll::Images::Cache.cached_image input
18
+ thumb = image.thumbnail(width: width,
19
+ height: height,
20
+ crop: crop,
21
+ auto_rotate: auto_rotate)
17
22
 
18
- image.write && image.optimize
19
- image.dest
23
+ thumb.write && thumb.optimize
24
+
25
+ thumb.url
20
26
  rescue Vips::Error => e
21
27
  Jekyll.logger.warn "Failed to process #{input}: #{e.message}"
22
28
  input
23
29
  end
24
-
25
- private
26
-
27
- def cached_image?(input)
28
- @@cached_images.key? input
29
- end
30
-
31
- def cached_image(input, width = nil, height = nil, crop = nil, auto_rotate = nil)
32
- @@cached_images[input] ||= Jekyll::Images::Thumbnail.new(@context.registers[:site],
33
- input,
34
- width: width,
35
- height: height,
36
- crop: crop,
37
- auto_rotate: auto_rotate)
38
- end
39
30
  end
40
31
  end
41
32
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Filters
5
+ # Obtain image width
6
+ module Width
7
+ def width(input)
8
+ return unless input
9
+ input = @context.registers[:site].in_source_dir input
10
+
11
+ unless ::File.exist? input
12
+ Jekyll.logger.warn "File doesn't exist #{input}"
13
+ return input
14
+ end
15
+
16
+ Jekyll::Images::Cache.cached_image(input).width
17
+ rescue Vips::Error => e
18
+ Jekyll.logger.warn "Failed to process #{input}: #{e.message}"
19
+ nil
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ Liquid::Template.register_filter(Jekyll::Filters::Width)
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Images
5
+ # Cache
6
+ class Cache
7
+ class << self
8
+ attr_accessor :site
9
+
10
+ def cached_images
11
+ @cached_images ||= {}
12
+ end
13
+
14
+ def cached_image?(input)
15
+ cached_images.key? input
16
+ end
17
+
18
+ def cached_image(input)
19
+ cached_images[input] ||= Jekyll::Images::Image.new(site, input)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'vips'
4
+
5
+ module Jekyll
6
+ module Images
7
+ class Image
8
+ attr_reader :site, :filename, :height, :width
9
+
10
+ def initialize(site, filename)
11
+ unless File.exist? filename
12
+ raise ArgumentError, "File not found: #{filename}"
13
+ end
14
+
15
+ @cached_thumbnails = {}
16
+ @site = site
17
+ @filename = filename
18
+
19
+ # We only need the image to get height and width
20
+ image = Vips::Image.new_from_file filename, access: :sequential
21
+
22
+ @height = image.height
23
+ @width = image.width
24
+ end
25
+
26
+ def thumbnail(**args)
27
+ @cached_thumbnails[args.hash.to_s] ||= Thumbnail.new site: site, filename: filename, image: self, **args
28
+ end
29
+ end
30
+ end
31
+ end
@@ -4,45 +4,41 @@ require 'vips'
4
4
 
5
5
  module Jekyll
6
6
  module Images
7
- # Use LibVIPS to generate images in different sizes
8
- #
9
- # We're assuming every image is going to be thumbnailed
10
7
  class Thumbnail
11
- attr_reader :site, :filename, :width, :height, :crop, :auto_rotate
8
+ attr_reader :site, :filename, :image, :width, :height, :crop, :auto_rotate
12
9
 
13
- def initialize(site, filename, **args)
14
- unless File.exist? filename
15
- raise ArgumentError, "File not found: #{filename}"
10
+ def initialize(site:, filename:, image:, **args)
11
+ if args.slice(:width, :height).values.none?
12
+ raise ArgumentError, "#{filename} thumbnail needs width or height"
16
13
  end
17
- raise ArgumentError, 'Missing width' unless args[:width]
18
14
 
19
15
  @site = site
20
16
  @filename = filename
21
- @width = args[:width]
22
- @height = args[:height]
23
- @crop = args[:crop].to_sym
24
- @auto_rotate = args[:auto_rotate]
25
- end
26
-
27
- def image
28
- @image ||= Vips::Image.new_from_file filename,
29
- access: :sequential
17
+ @image = image
18
+ @width = args[:width] || proportional_width(args[:height])
19
+ @height = args[:height] || proportional_height(args[:width])
20
+ @crop = args[:crop]&.to_sym || :attention
21
+ @auto_rotate = args[:auto_rotate].nil? ? true : args[:auto_rotate]
30
22
  end
31
23
 
24
+ # XXX: We don't memoize because we don't need the thumbnail in
25
+ # memory after it has been written.
32
26
  def thumbnail
33
- @thumbnail ||= image.thumbnail_image width,
34
- height: height,
35
- auto_rotate: auto_rotate,
36
- crop: crop
27
+ Vips::Image.thumbnail filename,
28
+ width,
29
+ height: height,
30
+ auto_rotate: auto_rotate,
31
+ crop: crop
37
32
  end
38
33
 
39
- def height
40
- @height || proportional_height
34
+ # Finds a height that's proportional to the width
35
+ def proportional_height(width)
36
+ @proportional_height ||= (image.height * (width / image.width.to_f)).round
41
37
  end
42
38
 
43
- # Finds a heigth that's proportional to the width
44
- def proportional_height
45
- @proportional_height ||= (image.height * (width / image.width.to_f)).round
39
+ # Find a width that's proportional to height
40
+ def proportional_width(height)
41
+ @proportional_width ||= (image.width * (height / image.height.to_f)).round
46
42
  end
47
43
 
48
44
  # Generates a destination from filename only if we're downsizing
@@ -54,6 +50,10 @@ module Jekyll
54
50
  end
55
51
  end
56
52
 
53
+ def url
54
+ static_file.url
55
+ end
56
+
57
57
  def thumbnail?
58
58
  image.width > width
59
59
  end
@@ -76,14 +76,13 @@ module Jekyll
76
76
  Jekyll.logger.info "Thumbnailing #{filename} => #{dest}"
77
77
  thumbnail.write_to_file(dest)
78
78
  else
79
+ Jekyll.logger.info "Copying #{filename} => #{dest}"
79
80
  FileUtils.cp(filename, dest)
80
81
  end
81
82
 
82
83
  # Add it to the static files so Jekyll copies them. Once they
83
84
  # are written they're copied when the site is loaded.
84
- site.static_files << Jekyll::StaticFile.new(site, site.source,
85
- File.dirname(dest),
86
- File.basename(dest))
85
+ site.static_files << static_file
87
86
 
88
87
  # The file was updated, so it exists and is newer than source
89
88
  !write?
@@ -99,6 +98,14 @@ module Jekyll
99
98
 
100
99
  Jekyll.logger.info "Reduced #{dest} from #{before} to #{after} bytes (%#{pct})"
101
100
  end
101
+
102
+ def relative_path
103
+ @relative_path ||= dest.sub(site.source, '').sub(%r{\A/}, '')
104
+ end
105
+
106
+ def static_file
107
+ @static_file ||= Jekyll::StaticFile.new(site, site.source, File.dirname(relative_path), File.basename(relative_path))
108
+ end
102
109
  end
103
110
  end
104
111
  end
data/lib/jekyll-images.rb CHANGED
@@ -1,6 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'jekyll/images/cache'
4
+
5
+ Jekyll::Images::Cache.site = Jekyll.sites.first
6
+
7
+ require_relative 'jekyll/images/image'
3
8
  require_relative 'jekyll/images/thumbnail'
4
9
  require_relative 'jekyll/filters/thumbnail'
10
+ require_relative 'jekyll/filters/width'
11
+ require_relative 'jekyll/filters/height'
5
12
  require_relative 'jekyll/images/oxipng'
6
13
  require_relative 'jekyll/images/jpeg_optim'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-images
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - f
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-20 00:00:00.000000000 Z
11
+ date: 2021-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -64,7 +64,11 @@ files:
64
64
  - LICENSE
65
65
  - README.md
66
66
  - lib/jekyll-images.rb
67
+ - lib/jekyll/filters/height.rb
67
68
  - lib/jekyll/filters/thumbnail.rb
69
+ - lib/jekyll/filters/width.rb
70
+ - lib/jekyll/images/cache.rb
71
+ - lib/jekyll/images/image.rb
68
72
  - lib/jekyll/images/jpeg_optim.rb
69
73
  - lib/jekyll/images/oxipng.rb
70
74
  - lib/jekyll/images/runner.rb
@@ -99,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
103
  - !ruby/object:Gem::Version
100
104
  version: '0'
101
105
  requirements: []
102
- rubygems_version: 3.0.3
106
+ rubygems_version: 3.1.2
103
107
  signing_key:
104
108
  specification_version: 4
105
109
  summary: Optimizes images for Jekyll