jekyll_img 0.2.6 → 0.2.8

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: 18a2afe029ee799d3c0afe05d58592b51aa2c49b2e6e880308963015ed43fe22
4
- data.tar.gz: efd819e05b6b0cfebf23f2eede44eb96ba5496b05a29c6dbb5bca748ce5bc9d2
3
+ metadata.gz: bc81e3ae00a242cf25f3444f45da2f621c692d6c7ee4760a17b59e8acc672c4d
4
+ data.tar.gz: 8b10b63f09b8b586343fd7a4ccc42c205ad1618cb9b422712d2300838799ead3
5
5
  SHA512:
6
- metadata.gz: ca437bd7388b2cd40b0c32ccc507352af61ff136aa3027b03cdecad617c12cde251642b8688356d1df1d41cacb1cb53652bbd2c683a6920606ebcf3cd9628ef9
7
- data.tar.gz: 6be7dd74a4281d01d430c67576febe041a8d872ff4068ebce9c8c95c7857974a1b5ec5dc24d43b5c464a48b0c910f99ecb432c9ddd2065ba34cb2254c196cf54
6
+ metadata.gz: 97b5302cf184c4fa544498354f1a8bae327f1567c438d88a232eef174422425d9e416bd6b0568439c1df2544cfb9b534e3cf0603931e00b9b2ff6a708c00abd5
7
+ data.tar.gz: a3ebcc031fb6e63dc92073cf358a38c7092719df8fbf028a5e3376d5b3447e3a539647d0825f47a47c27b45121345c91fecd1af99fc00b1ee816906b71d9c638
data/CHANGELOG.md CHANGED
@@ -1,6 +1,17 @@
1
1
  # Change Log
2
2
 
3
- ## 0.2.6 / 2024-08-30
3
+ ## 0.2.8 / 2025-05-16
4
+
5
+ * An image can now be lazily loaded by providing the `lazy` keyword.
6
+ * An image can now be fetched with high priority by providing the `priority` keyword.
7
+
8
+
9
+ ## 0.2.7 / 2024-09-11
10
+
11
+ * Further tweaking of the generated HTML.
12
+
13
+
14
+ ## 0.2.6 / 2024-09-10
4
15
 
5
16
  * Optimized the generated HTML.
6
17
  For example, `srcset` elements are now only generated for images that actually exit locally.
data/README.md CHANGED
@@ -74,6 +74,135 @@ If the browser did not support the `picture` element,
74
74
  the `img src` attribute would be used to specify the image.
75
75
 
76
76
 
77
+ ### Default and Relative Paths
78
+
79
+ Local images whose path does not start with a slash are assumed to be relative to `/assets/images`.
80
+ Simply specifying the filename of the image will cause it to be fetched from
81
+ `/assets/images/`.
82
+ For example, the following all fetch the same image:
83
+
84
+ ```html
85
+ {% img src="/assets/images/blah.webp" %}
86
+ {% img src="blah.webp" %}
87
+ {% img src="blah" %}
88
+ ```
89
+
90
+ To specify an image in a subdirectory of where the page resides,
91
+ prepend the relative path with a dot (`.`).
92
+
93
+ For example, if the current page resides in a [Jekyll collection](https://jekyllrb.com/docs/collections/)
94
+ with path `/collections/_av_studio/`,
95
+ and an image resides in the `/collections/_av_studio/images` subdirectory,
96
+ the following would result in the same image being displayed:
97
+
98
+ ```html
99
+ {% img src="/av_studio/images/blah" %}
100
+ {% img src="./images/blah" %}
101
+ ```
102
+
103
+ ### Lazy Loading
104
+
105
+ An image can be lazily loaded by providing the `lazy` keyword.
106
+ This feature relies upon the lazy loading capability built into all modern browsers and does not rely upon JavaScript.
107
+
108
+ From [Browser-level image lazy loading for the web](https://web.dev/articles/browser-level-image-lazy-loading#dimension-attributes)
109
+ on `web.dev`:
110
+
111
+ > While the browser loads an image, it doesn't immediately know the image's dimensions,
112
+ > unless they're explicitly specified.
113
+ > To let the browser reserve enough space on a page for images, and avoid disruptive layout shifts,
114
+ > we recommend adding width and height attributes to all tags.
115
+ >
116
+ > <img src="image.png" loading="lazy" alt="…" width="200" height="200">
117
+ Alternatively, specify their values directly in an inline style:
118
+ >
119
+ > <img src="image.png" loading="lazy" alt="…" style="height:200px; width:200px;">
120
+
121
+ This would translate to:
122
+
123
+ ```html
124
+ {% img lazy
125
+ src="blah.webp"
126
+ style="height:200px; width:200px"
127
+ %}
128
+ ```
129
+
130
+ Note that the image must be fetched in order for HTML `img` attributes `height='auto'` and `width='auto'` to work.
131
+ Thus lazy loading is incompatible with a dimension whose value is specified as `auto`.
132
+ This means that, for lazily loaded images,
133
+ `height` and `width` must have values that are computable without loading the image.
134
+ Because the Jekyll `img` tag's `size` attribute only specifies the `width` attribute,
135
+ and sets `height` to `auto`, it should not be used with the `lazy` keyword.
136
+
137
+ The following examples of implicit and explicit `auto` dimensions will all give problems:
138
+
139
+ ```html
140
+ {% img lazy
141
+ caption="A warning will be written to the logger"
142
+ size="200px"
143
+ src="blah.webp"
144
+ %}
145
+
146
+ {% img lazy
147
+ src="blah.webp"
148
+ style="height:auto; width:200px"
149
+ %}
150
+
151
+ {% img lazy
152
+ src="blah.webp"
153
+ style="height:200px; width:auto"
154
+ %}
155
+
156
+ {% img lazy
157
+ src="blah.webp"
158
+ style="height:200px"
159
+ %}
160
+
161
+ {% img lazy
162
+ src="blah.webp"
163
+ style="width:200px"
164
+ %}
165
+ ```
166
+
167
+
168
+ ### High Priority Loading
169
+
170
+ An image can be fetched with high priority by providing the `priority` keyword.
171
+
172
+ Sample usage:
173
+
174
+ ```html
175
+ {% img priority src="blah.webp" %}
176
+ ```
177
+
178
+ The above generates an HTML `img` tag with a `fetchpriority='high'` attribute.
179
+
180
+ From [Browser-level image lazy loading for the web](https://web.dev/articles/browser-level-image-lazy-loading#loading-priority)
181
+ on `web.dev`:
182
+
183
+ > If you want to increase the fetch priority of an important image, use `fetchpriority="high"`.
184
+ >
185
+ > An image with `loading="lazy"` and `fetchpriority="high"` is still delayed while it's off-screen,
186
+ > and then fetched with a high priority when it's almost within the viewport.
187
+ > This combination isn't really necessary because the browser would likely load that image with high priority anyway.
188
+
189
+
190
+ Note that the image must be fetched in order for `img` attributes `height='auto'` and `width='auto'` to work.
191
+ This means that `height` and `width` must have values that are computable without loading
192
+ the image or lazy loading will not work properly.
193
+ Because the `img` tag's `size` attribute only specifies the `width` attribute, and sets `height` to `auto`,
194
+ it should not be used.
195
+
196
+ Sample usage combining lazy and high priority loading:
197
+
198
+ ```html
199
+ {% img lazy priority
200
+ src="blah.webp"
201
+ style="height:200px; width:200px"
202
+ %}
203
+ ```
204
+
205
+
77
206
  ## Supported Filetypes
78
207
 
79
208
  The following are listed in order of priority.
@@ -199,7 +328,7 @@ Using CSS units means that large enough values could cause the image to exceed t
199
328
 
200
329
  ## Installation
201
330
 
202
- Add this line to your Jekyll project's Gemfile, within the `jekyll_plugins` group:
331
+ Add this line to your Jekyll project's `Gemfile`, within the `jekyll_plugins` group:
203
332
 
204
333
  ```ruby
205
334
  group :jekyll_plugins do
data/jekyll_img.gemspec CHANGED
@@ -3,11 +3,11 @@ require_relative 'lib/jekyll_img/version'
3
3
  Gem::Specification.new do |spec|
4
4
  github = 'https://github.com/mslinn/jekyll_img'
5
5
 
6
- spec.authors = ['Mike Slinn']
7
- spec.email = ['mslinn@mslinn.com']
8
- spec.files = Dir['.rubocop.yml', 'LICENSE.*', 'Rakefile', '{lib,spec}/**/*', '*.gemspec', '*.md']
6
+ spec.authors = ['Mike Slinn']
7
+ spec.email = ['mslinn@mslinn.com']
8
+ spec.files = Dir['.rubocop.yml', 'LICENSE.*', 'Rakefile', '{lib,spec}/**/*', '*.gemspec', '*.md']
9
9
  spec.homepage = 'https://www.mslinn.com/jekyll_plugins/jekyll_img.html'
10
- spec.license = 'MIT'
10
+ spec.license = 'MIT'
11
11
  spec.metadata = {
12
12
  'allowed_push_host' => 'https://rubygems.org',
13
13
  'bug_tracker_uri' => "#{github}/issues",
@@ -15,18 +15,20 @@ Gem::Specification.new do |spec|
15
15
  'homepage_uri' => spec.homepage,
16
16
  'source_code_uri' => github,
17
17
  }
18
- spec.name = 'jekyll_img'
18
+ spec.name = 'jekyll_img'
19
+ spec.platform = Gem::Platform::RUBY
19
20
  spec.post_install_message = <<~END_MESSAGE
20
21
 
21
22
  Thanks for installing #{spec.name}!
22
23
 
23
24
  END_MESSAGE
24
- spec.require_paths = ['lib']
25
+ spec.require_paths = ['lib']
25
26
  spec.required_ruby_version = '>= 2.6.0'
26
- spec.summary = 'Provides a Jekyll tag that generates images.'
27
- spec.test_files = spec.files.grep %r{^(test|spec|features)/}
28
- spec.version = JekyllImgVersion::VERSION
27
+ spec.summary = 'Provides a Jekyll tag that generates images.'
28
+ spec.test_files = spec.files.grep %r{^(test|spec|features)/}
29
+ spec.version = JekyllImgVersion::VERSION
29
30
 
30
31
  spec.add_dependency 'jekyll', '>= 3.5.0'
31
- spec.add_dependency 'jekyll_plugin_support', '>= 1.0.0'
32
+ spec.add_dependency 'jekyll_draft', '>= 3.0.0'
33
+ spec.add_dependency 'jekyll_plugin_support', '>= 3.0.0'
32
34
  end
data/lib/img_builder.rb CHANGED
@@ -1,5 +1,9 @@
1
- # Like RoR's squish method
2
1
  class String
2
+ def remove_blank_lines
3
+ strip.gsub(/^\s*$\n/, '')
4
+ end
5
+
6
+ # Like RoR's squish method
3
7
  def squish
4
8
  strip.gsub(/\s+/, ' ')
5
9
  end
@@ -7,107 +11,93 @@ end
7
11
 
8
12
  # Constructs HTML img tag from properties
9
13
  class ImgBuilder
10
- def initialize(props)
11
- props.compute_dependant_properties
12
- @props = props
13
- end
14
+ attr_reader :img, :props, :source
14
15
 
15
- def to_s
16
+ def initialize(img, props)
17
+ @img = img
18
+ @props = props
16
19
  @props.compute_dependant_properties
17
- generate_wrapper
20
+ @source = Source.new @props.src
18
21
  end
19
22
 
20
- private
21
-
22
- def generate_wrapper
23
- classes = "imgWrapper #{@props.img_display} #{@props.align} #{@props.attr_size_class} #{@props.wrapper_class}".squish
24
- result = <<~END_HTML
25
- <div class='#{classes}' style='#{@props.attr_width_style} #{@props.wrapper_style}'>
26
- #{"<figure>\n" if @props.caption}
27
- #{ if @props.url
28
- "<a href='#{@props.url}'#{@props.attr_target}#{@props.attr_nofollow} class='imgImgUrl'>#{generate_image}</a>"
29
- else
30
- generate_image
31
- end
32
- }
33
- #{generate_figure_caption}
34
- #{"</figure>\n" if @props.caption}
35
- #{@props.attribute if @props.attribution}
36
- </div>
37
- END_HTML
38
- result.strip.gsub(/^\s*$\n/, '')
39
- end
40
-
41
- def generate_figure_caption
42
- return nil unless @props.caption
43
-
23
+ def generate_figcaption
44
24
  <<~END_CAPTION
45
25
  <figcaption class='imgFigCaption #{@props.attr_size_class}'>
46
- #{if @props.url
47
- <<~END_URL
48
- <a href="#{@props.url}" #{@props.attr_target} #{@props.attr_nofollow}>
49
- #{@props.caption}
50
- </a>
51
- END_URL
52
- else
53
- @props.caption
54
- end
55
- }
26
+ #{@props.url ? generate_url_caption : @props.caption}
56
27
  </figcaption>
57
28
  END_CAPTION
58
29
  end
59
30
 
60
- # @return Array[String] containing HTML source elements
61
- def generate_sources(filetypes, mimetype)
62
- result = filetypes.map do |ftype|
63
- filename = @props.src_any ftype
64
- next unless filename.start_with?('http') || File.exist?("./#{filename}")
65
-
66
- <<~END_HTML
67
- <source srcset="#{filename}" type="#{mimetype}">
68
- END_HTML
69
- end
70
- result&.compact&.map(&:strip)
71
- end
72
-
73
- def generate_compact_sources
74
- [
75
- generate_sources(%w[svg], 'image/svg'),
76
- generate_sources(%w[webp], 'image/webp'),
77
- generate_sources(%w[png], 'image/png'),
78
- generate_sources(%w[apng], 'image/apng'),
79
- generate_sources(%w[jpg jpeg jfif pjpeg pjp], 'image/jpeg'),
80
- generate_sources(%w[gif], 'image/gif'),
81
- generate_sources(%w[tif tiff], 'image/tiff'),
82
- generate_sources(%w[bmp], 'image/bmp'),
83
- generate_sources(%w[cur ico], 'image/x-icon')
84
- ].compact.join("\n").strip.gsub(/^$\n/, '')
31
+ def generate_img
32
+ img_classes = @props.classes || 'rounded shadow'
33
+ <<~END_IMG
34
+ <img #{@props.attr_alt}
35
+ class="imgImg #{img_classes.squish}"
36
+ src="#{@source.src_fallback}"
37
+ #{@props.attr_style_img}
38
+ #{@props.attr_title}
39
+ #{@props.lazy}
40
+ #{@props.priority}
41
+ />
42
+ END_IMG
85
43
  end
86
44
 
87
45
  # See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture
88
- def generate_image
46
+ def generate_picture
47
+ if @props.lazy && @props.size
48
+ @img.logger.warn do
49
+ <<~END_MSG.squish
50
+ Warning: lazy loading was specified, but the size attribute was specified for the href tag
51
+ on line #{@img.line_number} (after front matter) of #{@img.page['path']}.
52
+ Specify dimensions via style or class attributes instead.
53
+ END_MSG
54
+ end
55
+ end
56
+
89
57
  return generate_img if @props.src.start_with? 'http'
90
58
 
91
59
  # avif is not well supported yet
92
60
  # <source srcset="#{@props.src_any 'avif'}" type="image/avif">
93
61
  result = <<~END_IMG
94
62
  <picture#{@props.attr_id} class='imgPicture'>
95
- #{generate_compact_sources}
63
+ #{@source.generate.join("\n ")}
96
64
  #{generate_img}
97
65
  </picture>
98
66
  END_IMG
99
67
  result.strip
100
68
  end
101
69
 
102
- def generate_img
103
- img_classes = @props.classes || 'rounded shadow'
104
- <<~END_IMG
105
- <img #{@props.attr_alt}
106
- class="imgImg #{img_classes.squish}"
107
- src="#{@props.src_png}"
108
- #{@props.attr_style_img}
109
- #{@props.attr_title}
110
- />
111
- END_IMG
70
+ def generate_url_caption
71
+ <<~END_URL
72
+ <a href="#{@props.url}"#{@props.attr_target}#{@props.attr_nofollow}>
73
+ #{@props.caption}
74
+ </a>
75
+ END_URL
76
+ end
77
+
78
+ def generate_url_wrapper
79
+ <<~END_HTML
80
+ <a href='#{@props.url}'#{@props.attr_target}#{@props.attr_nofollow} class='imgImgUrl'>
81
+ #{generate_picture}
82
+ </a>
83
+ END_HTML
84
+ end
85
+
86
+ def generate_wrapper
87
+ classes = "imgWrapper #{@props.img_display} #{@props.align} #{@props.attr_size_class} #{@props.wrapper_class}".squish
88
+ <<~END_HTML.remove_blank_lines
89
+ <div class='#{classes}' style='#{@props.attr_width_style} #{@props.wrapper_style}'>
90
+ #{"<figure>\n" if @props.caption}
91
+ #{@props.url ? generate_url_wrapper : generate_picture}
92
+ #{generate_figcaption if @props.caption}
93
+ #{"</figure>\n" if @props.caption}
94
+ #{@props.attribute if @props.attribution}
95
+ </div>
96
+ END_HTML
97
+ end
98
+
99
+ def to_s
100
+ @props.compute_dependant_properties
101
+ generate_wrapper
112
102
  end
113
103
  end
data/lib/img_props.rb CHANGED
@@ -6,10 +6,11 @@ require 'uri'
6
6
  # All methods except compute_dependant_properties can be called in any order
7
7
  class ImgProperties
8
8
  attr_accessor :align, :alt, :attr_wrapper_align_class, :attribute, :attribution, :caption, :classes, :die_on_img_error,
9
- :id, :img_display, :local_src, :nofollow, :src, :size, :style, :target, :title,
9
+ :id, :img_display, :lazy, :local_src, :nofollow, :priority, :src, :size, :style, :target, :title,
10
10
  :url, :wrapper_class, :wrapper_style
11
11
 
12
12
  SIZES = %w[eighthsize fullsize halfsize initial quartersize].freeze
13
+ UNITS = %w[Q ch cm em dvh dvw ex in lh lvh lvw mm pc px pt rem rlh svh svw vb vh vi vmax vmin vw %].freeze
13
14
 
14
15
  def attr_alt
15
16
  "alt='#{@alt}'" if @alt
@@ -69,13 +70,7 @@ class ImgProperties
69
70
  end
70
71
 
71
72
  def src_any(filetype)
72
- @src.gsub('.webp', ".#{filetype}")
73
- end
74
-
75
- def src_png
76
- raise Jekyll::ImgError, "The 'src' parameter was not specified" if @src.to_s.empty?
77
-
78
- @src.gsub('.webp', '.png')
73
+ @src.gsub(/\..*?$/, ".#{filetype}")
79
74
  end
80
75
 
81
76
  def self.local_path?(src)
@@ -86,7 +81,7 @@ class ImgProperties
86
81
  private
87
82
 
88
83
  def setup_src
89
- raise Jekyll::ImgError, "The 'src' parameter was not specified" if @src.nil?
84
+ raise Jekyll::ImgError, "The 'src' parameter was not specified" if @src.nil? || [true, false].include?(@src)
90
85
 
91
86
  raise Jekyll::ImgError, "The 'src' parameter was empty" if @src.empty?
92
87
 
@@ -103,8 +98,6 @@ class ImgProperties
103
98
  # raise Jekyll::ImgError, "#{@src} does not exist" unless File.exist?(src)
104
99
  end
105
100
 
106
- UNITS = %w[Q ch cm em dvh dvw ex in lh lvh lvw mm pc px pt rem rlh svh svw vb vh vi vmax vmin vw %].freeze
107
-
108
101
  def size_unit_specified?
109
102
  return false if @size == false || @size.to_s.strip.empty?
110
103
 
@@ -1,3 +1,3 @@
1
1
  module JekyllImgVersion
2
- VERSION = '0.2.6'.freeze
2
+ VERSION = '0.2.8'.freeze
3
3
  end
data/lib/jekyll_img.rb CHANGED
@@ -3,6 +3,7 @@ require 'helper/jekyll_plugin_helper'
3
3
  require 'pry'
4
4
  require_relative 'img_builder'
5
5
  require_relative 'img_props'
6
+ require_relative 'source'
6
7
  require_relative 'jekyll_img/version'
7
8
 
8
9
  # @author Copyright 2023 Michael Slinn
@@ -34,7 +35,9 @@ module Jekyll
34
35
  props.classes = @helper.parameter_specified? 'class'
35
36
  props.die_on_img_error = @die_on_img_error
36
37
  props.id = @helper.parameter_specified? 'id'
38
+ props.lazy = ' loading="lazy"' if @helper.parameter_specified?('lazy')
37
39
  props.nofollow = @helper.parameter_specified? 'nofollow'
40
+ props.priority = ' fetchpriority="high"' if @helper.parameter_specified?('priority')
38
41
  props.size = @helper.parameter_specified?('size') || @helper.parameter_specified?('_size')
39
42
  props.src = @helper.parameter_specified? 'src'
40
43
  props.style = @helper.parameter_specified? 'style'
@@ -44,7 +47,7 @@ module Jekyll
44
47
  props.wrapper_class = @helper.parameter_specified? 'wrapper_class'
45
48
  props.wrapper_style = @helper.parameter_specified? 'wrapper_style'
46
49
 
47
- @builder = ImgBuilder.new(props)
50
+ @builder = ImgBuilder.new(self, props)
48
51
  @builder.to_s
49
52
  rescue ImgError => e # jekyll_plugin_support handles StandardError
50
53
  @logger.error { e.logger_message }
data/lib/source.rb ADDED
@@ -0,0 +1,98 @@
1
+ class Source
2
+ RANKS = %w[svg webp apng png jpg jpeg jfif pjpeg pjp gif tif tiff bmp cur ico].freeze
3
+ RANKS_LENGTH = RANKS.length
4
+
5
+ def initialize(path)
6
+ raise Jekyll::ImgError, "The 'src' parameter was not specified" if path.nil?
7
+ raise Jekyll::ImgError, "The 'src' parameter was empty" if path.empty?
8
+
9
+ path.strip!
10
+ raise Jekyll::ImgError, "The 'src' parameter only contained whitespace" if path.empty?
11
+
12
+ @path = path
13
+ @absolute_path = @path.start_with?('/')
14
+ end
15
+
16
+ # @return array of source statements for filetypes that exist locally;
17
+ # return nil if @path points to a remote image
18
+ def generate
19
+ return nil if @path.nil? || @path.start_with?('http')
20
+
21
+ result = sorted_files.map do |filename|
22
+ mtype = mimetype filename
23
+ next unless mtype
24
+
25
+ <<~END_HTML
26
+ <source srcset="#{filename}" type="#{mtype}">
27
+ END_HTML
28
+ end
29
+ result&.compact&.map(&:strip)
30
+ end
31
+
32
+ # Webp is the least desired variant, png is most desired variant.
33
+ # @return URL of external image, otherwise return specified path unless it is a webp;
34
+ # in which case return most desired image variant that exists.
35
+ def src_fallback
36
+ return @path if @path.start_with? 'http'
37
+
38
+ result = @absolute_path ? @path.delete_prefix('.') : @path
39
+ png = result.gsub(/\.webp$/, '.png')
40
+ return png if File.exist? png
41
+ return result unless result.end_with? '.webp' # we know @path will be a webp after this
42
+
43
+ files = sorted_files
44
+ return files[0] if files.count == 1
45
+
46
+ files.each do |filename|
47
+ ext = File.extname filename
48
+ unless ext == '.webp'
49
+ return @absolute_path ? filename.delete_prefix('.') : filename
50
+ end
51
+ end
52
+ result
53
+ end
54
+
55
+ private
56
+
57
+ # Convert absolute paths (which reference the website root) to relative paths for globbing
58
+ def globbed_path
59
+ dir = File.dirname @path
60
+ dir = ".#{dir}" if dir.start_with?('/')
61
+ base = File.basename @path, ".*"
62
+ "#{dir}/#{base}.*"
63
+ end
64
+
65
+ def mimetype(path)
66
+ case File.extname(path)
67
+ when '.svg'
68
+ 'image/svg'
69
+ when '.webp'
70
+ 'image/webp'
71
+ when '.png'
72
+ 'image/png'
73
+ when '.apng'
74
+ 'image/apng'
75
+ when %w[.jpg .jpeg .jfif .pjpeg .pjp]
76
+ 'image/jpeg'
77
+ when '.gif'
78
+ 'image/gif'
79
+ when %w[.tif .tiff]
80
+ 'image/tiff'
81
+ when '.bmp'
82
+ 'image/bmp'
83
+ when %w[cur ico]
84
+ 'image/x-icon'
85
+ # else
86
+ # raise Jekyll::ImgError, "#{path} has an unrecognized filetype."
87
+ end
88
+ end
89
+
90
+ def sorted_files
91
+ sorted = Dir[globbed_path].sort_by do |path|
92
+ ext = File.extname(path)&.delete_prefix('.')
93
+ index = RANKS.index(ext)
94
+ index || RANKS_LENGTH
95
+ end
96
+ sorted.map { |x| @absolute_path ? x.delete_prefix('.') : x }
97
+ end
98
+ end
@@ -1,25 +1,50 @@
1
1
  require 'rspec/match_ignoring_whitespace'
2
2
  require_relative '../lib/img_builder'
3
3
  require_relative '../lib/img_props'
4
+ require_relative '../lib/source'
4
5
 
5
6
  # Test ImgProperties
6
7
  class ImgPropertiesTest
7
8
  RSpec.describe ImgBuilder do
8
9
  Dir.chdir("demo")
10
+ props = ImgProperties.new
11
+ props.src = '/assets/images/jekyll.webp'
12
+ builder = described_class.new(props)
9
13
 
10
14
  it 'generates sources' do
11
- props = ImgProperties.new
12
- props.src = 'jekyll.webp'
13
- builder = described_class.new(props)
14
- actual = builder.send(:generate_sources, ['png'], 'image/png')
15
- expect(actual).to contain_exactly('<source srcset="/assets/images/jekyll.png" type="image/png">')
15
+ actual = builder.source.generate
16
+ desired = [
17
+ '<source srcset="/assets/images/jekyll.webp" type="image/webp">',
18
+ '<source srcset="/assets/images/jekyll.png" type="image/png">'
19
+ ]
20
+ expect(actual).to match_array(desired)
21
+ end
22
+
23
+ it 'generates a figcaption' do
24
+ desired = <<~END_STRING
25
+ <figcaption class='imgFigCaption '>
26
+ </figcaption>
27
+ END_STRING
28
+ expect(builder.generate_figcaption).to match_ignoring_whitespace(desired)
29
+ end
30
+
31
+ it 'generates a picture' do
32
+ desired = <<~END_DESIRED
33
+ <picture class='imgPicture'>
34
+ <source srcset="/assets/images/jekyll.webp" type="image/webp">
35
+ <source srcset="/assets/images/jekyll.png" type="image/png">
36
+ <img class="imgImg rounded shadow"
37
+ src="/assets/images/jekyll.png"
38
+ style='width: 100%; '
39
+ />
40
+ </picture>
41
+ END_DESIRED
42
+ actual = builder.generate_picture
43
+ expect(actual).to match_ignoring_whitespace(desired)
16
44
  end
17
45
 
18
46
  it 'generates a default img' do
19
- props = ImgProperties.new
20
- props.src = 'jekyll.webp'
21
- builder = described_class.new(props)
22
- picture = <<~END_IMG
47
+ desired = <<~END_IMG
23
48
  <div class='imgWrapper imgFlex' style=' '>
24
49
  <picture class='imgPicture'>
25
50
  <source srcset="/assets/images/jekyll.webp" type="image/webp">
@@ -32,15 +57,13 @@ class ImgPropertiesTest
32
57
  </div>
33
58
  END_IMG
34
59
 
35
- expect(builder.send(:generate_figure_caption)).to be_nil
36
- expect(builder.send(:generate_wrapper)).to match_ignoring_whitespace(picture)
60
+ actual = builder.generate_wrapper
61
+ expect(actual).to match_ignoring_whitespace(desired)
37
62
  end
38
63
 
39
- it 'generates an img with size and caption' do
40
- props = ImgProperties.new
64
+ it 'generates an img wrapper with size and caption' do
41
65
  props.caption = 'This is a caption'
42
66
  props.size = '123px'
43
- props.src = 'jekyll.webp'
44
67
  builder = described_class.new(props)
45
68
 
46
69
  caption = <<~END_CAPTION
@@ -49,7 +72,7 @@ class ImgPropertiesTest
49
72
  </figcaption>
50
73
  END_CAPTION
51
74
 
52
- picture = <<~END_IMG
75
+ desired = <<~END_IMG
53
76
  <div class='imgWrapper imgBlock' style='width: 123px; '>
54
77
  <figure>
55
78
  <picture class='imgPicture'>
@@ -67,8 +90,8 @@ class ImgPropertiesTest
67
90
  </div>
68
91
  END_IMG
69
92
 
70
- expect(builder.send(:generate_figure_caption)).to match_ignoring_whitespace(caption)
71
- expect(builder.send(:generate_wrapper)).to match_ignoring_whitespace(picture)
93
+ actual = builder.generate_wrapper
94
+ expect(actual).to match_ignoring_whitespace(desired)
72
95
  end
73
96
  end
74
97
  end
@@ -1,6 +1,6 @@
1
1
  require_relative '../lib/img_props'
2
2
 
3
- class ImgProperitesTest
3
+ class ImgPropertiesTest
4
4
  RSpec.describe ImgProperties do
5
5
  it 'detects relative paths' do
6
6
  expect(described_class.local_path?('abcdef')).to be false
@@ -37,7 +37,7 @@ class ImgProperitesTest
37
37
 
38
38
  it 'raises exception if src was not specified' do
39
39
  props = described_class.new
40
- expect { props.src_png }.to raise_error(Jekyll::ImgError)
40
+ expect { props.compute_dependant_properties }.to raise_error(Jekyll::ImgError)
41
41
  expect { props.send(:setup_src) }.to raise_error(Jekyll::ImgError)
42
42
 
43
43
  props.src = 'relative/path.webp'
@@ -56,7 +56,7 @@ class MyTest
56
56
  )
57
57
  end
58
58
 
59
- it 'has no cite or url' do
59
+ xit 'has no cite or url' do
60
60
  helper.reinitialize('src="./blah.webp"')
61
61
  img = described_class.send(
62
62
  :new,
@@ -64,10 +64,11 @@ class MyTest
64
64
  helper.markup.dup,
65
65
  parse_context
66
66
  )
67
- result = img.send(:render_impl)
68
- expect(result).to match_ignoring_whitespace <<-END_RESULT
67
+ actual = img.render_impl
68
+ desired = <<~END_DESIRED
69
69
  <img src="./blah.webp">
70
- END_RESULT
70
+ END_DESIRED
71
+ expect(actual).to match_ignoring_whitespace(desired)
71
72
  end
72
73
  end
73
74
  end
@@ -0,0 +1,87 @@
1
+ require 'rspec/match_ignoring_whitespace'
2
+ require_relative '../lib/source'
3
+
4
+ # Test ImgProperties
5
+ class ImgPropertiesTest
6
+ RSpec.describe Source do
7
+ Dir.chdir("#{__dir__}/../demo")
8
+ source_absolute = described_class.new('/assets/images/jekyll_240x103.webp')
9
+ source_relative = described_class.new('./assets/images/jekyll_240x103.webp')
10
+
11
+ it 'globs absolute paths' do
12
+ expect(source_absolute.send(:globbed_path)).to eq("./assets/images/jekyll_240x103.*")
13
+ end
14
+
15
+ it 'globs relative paths' do
16
+ expect(source_relative.send(:globbed_path)).to eq("./assets/images/jekyll_240x103.*")
17
+ end
18
+
19
+ it 'sorts files with absolute path' do
20
+ actual = source_absolute.send(:sorted_files)
21
+ desired = [
22
+ "/assets/images/jekyll_240x103.webp",
23
+ "/assets/images/jekyll_240x103.png",
24
+ "/assets/images/jekyll_240x103.jpg",
25
+ "/assets/images/jekyll_240x103.gif",
26
+ "/assets/images/jekyll_240x103.txt"
27
+ ]
28
+ expect(actual).to eq(desired)
29
+ end
30
+
31
+ it 'sorts files with relative path' do
32
+ actual = source_relative.send(:sorted_files)
33
+ desired = [
34
+ "./assets/images/jekyll_240x103.webp",
35
+ "./assets/images/jekyll_240x103.png",
36
+ "./assets/images/jekyll_240x103.jpg",
37
+ "./assets/images/jekyll_240x103.gif",
38
+ "./assets/images/jekyll_240x103.txt"
39
+ ]
40
+ expect(actual).to eq(desired)
41
+ end
42
+
43
+ it 'generates mimetype for absolute paths' do
44
+ expect(source_absolute.send(:mimetype, 'blah.png')).to eq('image/png')
45
+ expect(source_absolute.send(:mimetype, 'blah.svg')).to eq('image/svg')
46
+ expect(source_absolute.send(:mimetype, 'blah.webp')).to eq('image/webp')
47
+ expect(source_absolute.send(:mimetype, 'blah.gif')).to eq('image/gif')
48
+ expect(source_absolute.send(:mimetype, 'blah.blah')).to be_nil
49
+ end
50
+
51
+ it 'generates mimetype for relative paths' do
52
+ expect(source_relative.send(:mimetype, 'blah.png')).to eq('image/png')
53
+ expect(source_relative.send(:mimetype, 'blah.svg')).to eq('image/svg')
54
+ expect(source_relative.send(:mimetype, 'blah.webp')).to eq('image/webp')
55
+ expect(source_relative.send(:mimetype, 'blah.gif')).to eq('image/gif')
56
+ expect(source_relative.send(:mimetype, 'blah.blah')).to be_nil
57
+ end
58
+
59
+ it 'generates source fallback for absolute paths' do
60
+ expect(source_absolute.src_fallback).to eq("/assets/images/jekyll_240x103.png")
61
+ end
62
+
63
+ it 'generates source fallback for relative paths' do
64
+ expect(source_relative.src_fallback).to eq("./assets/images/jekyll_240x103.png")
65
+ end
66
+
67
+ it 'generates sources for absolute paths' do
68
+ actual = source_absolute.generate.join("\n")
69
+ desired = <<~END_DESIRED
70
+ <source srcset="/assets/images/jekyll_240x103.webp" type="image/webp">
71
+ <source srcset="/assets/images/jekyll_240x103.png" type="image/png">
72
+ <source srcset="/assets/images/jekyll_240x103.gif" type="image/gif">
73
+ END_DESIRED
74
+ expect(actual).to match_ignoring_whitespace(desired)
75
+ end
76
+
77
+ it 'generates sources for relative paths' do
78
+ actual = source_relative.generate.join("\n")
79
+ desired = <<~END_DESIRED
80
+ <source srcset="./assets/images/jekyll_240x103.webp" type="image/webp">
81
+ <source srcset="./assets/images/jekyll_240x103.png" type="image/png">
82
+ <source srcset="./assets/images/jekyll_240x103.gif" type="image/gif">
83
+ END_DESIRED
84
+ expect(actual).to match_ignoring_whitespace(desired)
85
+ end
86
+ end
87
+ end
@@ -3,8 +3,14 @@ example_id | status | run_time |
3
3
  ./spec/img_builder_spec.rb[1:1] | failed | 14.37 seconds |
4
4
  ./spec/img_builder_spec.rb[1:2] | failed | 0.01498 seconds |
5
5
  ./spec/img_builder_spec.rb[1:3] | failed | 0.00093 seconds |
6
- ./spec/img_props_spec.rb[1:1] | passed | 0.00407 seconds |
7
- ./spec/img_props_spec.rb[1:2] | passed | 0.00005 seconds |
8
- ./spec/img_props_spec.rb[1:3] | passed | 0.00845 seconds |
9
- ./spec/img_props_spec.rb[1:4] | passed | 0.00135 seconds |
10
- ./spec/img_props_spec.rb[1:5] | passed | 11.17 seconds |
6
+ ./spec/img_props_spec.rb[1:1] | passed | 0.00393 seconds |
7
+ ./spec/img_props_spec.rb[1:2] | passed | 0.00006 seconds |
8
+ ./spec/img_props_spec.rb[1:3] | passed | 0.00673 seconds |
9
+ ./spec/img_props_spec.rb[1:4] | passed | 4.65 seconds |
10
+ ./spec/img_props_spec.rb[1:5] | passed | 0.00009 seconds |
11
+ ./spec/jekyll_img_spec.rb[1:1] | failed | 40.84 seconds |
12
+ ./spec/source_spec.rb[1:1] | passed | 0.00089 seconds |
13
+ ./spec/source_spec.rb[1:2] | passed | 0.0045 seconds |
14
+ ./spec/source_spec.rb[1:3] | passed | 0.00687 seconds |
15
+ ./spec/source_spec.rb[1:4] | passed | 0.00071 seconds |
16
+ ./spec/source_spec.rb[1:5] | passed | 1.72 seconds |
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll_img
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Slinn
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-08-31 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: jekyll
@@ -24,21 +23,34 @@ dependencies:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
25
  version: 3.5.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: jekyll_draft
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 3.0.0
27
40
  - !ruby/object:Gem::Dependency
28
41
  name: jekyll_plugin_support
29
42
  requirement: !ruby/object:Gem::Requirement
30
43
  requirements:
31
44
  - - ">="
32
45
  - !ruby/object:Gem::Version
33
- version: 1.0.0
46
+ version: 3.0.0
34
47
  type: :runtime
35
48
  prerelease: false
36
49
  version_requirements: !ruby/object:Gem::Requirement
37
50
  requirements:
38
51
  - - ">="
39
52
  - !ruby/object:Gem::Version
40
- version: 1.0.0
41
- description:
53
+ version: 3.0.0
42
54
  email:
43
55
  - mslinn@mslinn.com
44
56
  executables: []
@@ -55,9 +67,11 @@ files:
55
67
  - lib/img_props.rb
56
68
  - lib/jekyll_img.rb
57
69
  - lib/jekyll_img/version.rb
70
+ - lib/source.rb
58
71
  - spec/img_builder_spec.rb
59
72
  - spec/img_props_spec.rb
60
73
  - spec/jekyll_img_spec.rb
74
+ - spec/source_spec.rb
61
75
  - spec/spec_helper.rb
62
76
  - spec/status_persistence.txt
63
77
  homepage: https://www.mslinn.com/jekyll_plugins/jekyll_img.html
@@ -87,14 +101,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
101
  - !ruby/object:Gem::Version
88
102
  version: '0'
89
103
  requirements: []
90
- rubygems_version: 3.5.17
91
- signing_key:
104
+ rubygems_version: 3.6.9
92
105
  specification_version: 4
93
106
  summary: Provides a Jekyll tag that generates images.
94
107
  test_files:
95
108
  - spec/img_builder_spec.rb
96
109
  - spec/img_props_spec.rb
97
110
  - spec/jekyll_img_spec.rb
111
+ - spec/source_spec.rb
98
112
  - spec/spec_helper.rb
99
113
  - spec/status_persistence.txt
100
114
  ...