jekyll_img 0.2.5 → 0.2.7

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: 68b1a33d89b04dfab1851a2ba9adaac2ebeb7b7fbd91428cb2431f008f9226a1
4
- data.tar.gz: ac86e8906b8d5e96d7295486f8e7b0ac2f76a825e2f9cd66d6072a5e644c0fb3
3
+ metadata.gz: 0ec131406e5dce078a0d63a5a821f73b8de66ece127990a8c3fa34a348c9d819
4
+ data.tar.gz: ed9c9f00d0df3b50ea9409593ccc58fa6aca91d2e8c200a4ece28a8b3fc21aa3
5
5
  SHA512:
6
- metadata.gz: f44391734629f99eedf6d62579bf3e4342ba334f20b6bc7b67e6a046cca8f774cc8e181fbc9c5c4c0661d6ba532c6cc525a8de62cf6f5ce049eea4c7766bc0b5
7
- data.tar.gz: d7fa41d16eb7b23368ce08dddb59574a5c71b5a4afab28705bd16b44ab7b10d527db90e068d51ef91780e1cb950fb1a23953bc5d1922d2c0800a1d81418d34fc
6
+ metadata.gz: 256b5e033e1f7ab3b08a0e37df0091eb39c67430397da6fb44745cd29e0dbc46fa104efe88b4230ca8d17ecb47014006ae11031895f14cf7031632e702f8cf0d
7
+ data.tar.gz: 15a4431e31fdef70e180dc0a774f9a9eff410276768d42a7f3b727a72f1b1c30fd87a6242199ddf0898bb1e0fa17aa43ce70cf67b727b3981d85be1aa4ede188
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.2.7 / 2024-09-11
4
+
5
+ * Further tweaking of the generated HTML.
6
+
7
+
8
+ ## 0.2.6 / 2024-09-10
9
+
10
+ * Optimized the generated HTML.
11
+ For example, `srcset` elements are now only generated for images that actually exit locally.
12
+ For remote images, only an `img` element is generated for the specified filetype.
13
+ The tests can be found in `demo/img_test.html`.
14
+
15
+
3
16
  ## 0.2.5 / 2024-07-23
4
17
 
5
18
  * Depends on jekyll_plugin_support v1.0.2
data/README.md CHANGED
@@ -9,10 +9,6 @@ Muliple image formats are supported for each image.
9
9
  The user’s web browser determines the formats which it will accept.
10
10
  The most desirable formats that the web browser supports are prioritized.
11
11
 
12
- I explain why the `webp` image format is important in
13
- [Converting All Images in a Website to `webp` Format](https://mslinn.com/blog/2020/08/15/converting-all-images-to-webp-format.html).
14
- That article also provides 2 bash scripts for converting existing images to and from <code>webp</code> format.
15
-
16
12
  For example, if an image is encloded in `webp`, `png` and `gif` filetypes,
17
13
  and the user&rsquo;s web browser is relatively recent,
18
14
  then `webp` format will give the fastest transmission and look best.
@@ -22,56 +18,87 @@ Really old web browsers would only support the `gif` file type.
22
18
 
23
19
  Please read the next section for details.
24
20
 
21
+ I explain why the `webp` image format is important in
22
+ [Converting All Images in a Website to `webp` Format](https://mslinn.com/blog/2020/08/15/converting-all-images-to-webp-format.html).
23
+ That article also provides 2 bash scripts for converting existing images to and from <code>webp</code> format.
24
+
25
25
  See [demo/index.html](demo/index.html) for examples.
26
26
 
27
27
 
28
+ ## External Images
29
+
30
+ Images whose `src` attribute starts with `http` are not served from the Jekyll website.
31
+ The `jekyll_img` plugin generates HTML for external images using an `img` element with a `src`
32
+ attribute as you might expect.
33
+
34
+
28
35
  ## Image Fallback
29
36
 
30
- This plugin provides support for many image formats,
31
- fallbacks to less performant formats by using the HTML
37
+ For local files (files served from the Jekyll website),
38
+ the `jekyll_img` plugin generates HTML that falls back to successively less performant
39
+ formats.
40
+ This is made possible by using a
32
41
  [`picture`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture) element.
33
42
 
34
- This means that at least one version of every image are required.
43
+ At least one version of every image are required.
44
+ Supported filetypes are:
45
+ `svg`, `webp`, `apng`, `png`, `jpg`, `jpeg`, `jfif`, `pjpeg`, `pjp`, `gif`, `tif`, `tiff`, `bmp`, `ico` and `cur`.
35
46
 
36
- You could specify the desired image with a `webp` filetype, or you could specify no filetype.
37
- The plugin would generate a `picture` element that contains a primary
38
- `source` sub-element that specifies the given image URL,
39
- and secondary `img` sub-element with all other supported filetypes.
40
-
41
- For example, these two invocations yield the same result:
47
+ For example, an image file might have the following verions: `blah.webp`, `blah.png` and `blah.jpg`.
48
+ Given a tag invocation like `{% img src='blah.webp' %}`,
49
+ the plugin would generate a `picture` element that contains an `img` sub-element with the given `src` attribute,
50
+ and a `source` element for each related image (`blah.png` and `blah.jpg`).
51
+ Conceptually, the generated HTML might look something like this:
42
52
 
43
53
  ```html
44
- {% img src="blah" %}
45
- {% img src="blah.webp" %}
54
+ <picture>
55
+ <source srcset="blah.png" />
56
+ <source srcset="blah.jpg" />
57
+ <img src="blah.webp" />
58
+ </picture>
46
59
  ```
47
60
 
48
- The above generates the following
49
- (to support the other options, the generated HTML can be a lot more complex):
61
+ If no filetype is given for the image, `webp` is assumed.
62
+ For example, these two invocations yield the same result,
63
+ if `blah.webp` exists on the Jekyll website:
50
64
 
51
65
  ```html
52
- <picture>
53
- <source srcset="blah.svg" type="image/svg" />
54
- <source srcset="blah.webp" type="image/webp" />
55
- <source srcset="blah.apng" type="image/apng">
56
- <source srcset="blah.png" type="image/png">
57
- <source srcset="blah.jpg" type="image/jpeg">
58
- <source srcset="blah.jpeg" type="image/jpeg">
59
- <source srcset="blah.jfif" type="image/jpeg">
60
- <source srcset="blah.pjpeg" type="image/jpeg">
61
- <source srcset="blah.pjp" type="image/jpeg">
62
- <source srcset="blah.gif" type="image/gif">
63
- <source srcset="blah.tif" type="image/tiff">
64
- <source srcset="blah.tiff" type="image/tiff">
65
- <source srcset="blah.bmp" type="image/bmp">
66
- <source srcset="blah.ico" type="image/x-icon">
67
- <source srcset="blah.cur" type="image/x-icon">
68
- <img src="blah.png" />
69
- </picture>
66
+ {% img src="blah" %}
67
+ {% img src="blah.webp" %}
70
68
  ```
71
69
 
72
70
  If both `blah.webp` and `blah.png` were available,
73
71
  the above would fetch and display `blah.webp` if the web browser supported `webp` format,
74
72
  otherwise it would fetch and display `blah.png`.
73
+ If the browser did not support the `picture` element,
74
+ the `img src` attribute would be used to specify the image.
75
+
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
+ ```
75
102
 
76
103
 
77
104
  ## Supported Filetypes
@@ -103,7 +130,7 @@ Run the demo website by typing:
103
130
  $ demo/_bin/debug -r
104
131
  ```
105
132
 
106
- ... and point your web browser to http://localhost:4444
133
+ ... and point your web browser to http://localhost:4011
107
134
 
108
135
 
109
136
  ## Usage
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,84 +11,80 @@ end
7
11
 
8
12
  # Constructs HTML img tag from properties
9
13
  class ImgBuilder
14
+ attr_reader :source
15
+
10
16
  def initialize(props)
11
17
  props.compute_dependant_properties
12
18
  @props = props
19
+ @source = Source.new @props.src
13
20
  end
14
21
 
15
- def to_s
16
- @props.compute_dependant_properties
17
- generate_wrapper
22
+ def generate_figcaption
23
+ <<~END_CAPTION
24
+ <figcaption class='imgFigCaption #{@props.attr_size_class}'>
25
+ #{@props.url ? generate_url_caption : @props.caption}
26
+ </figcaption>
27
+ END_CAPTION
28
+ end
29
+
30
+ def generate_img
31
+ img_classes = @props.classes || 'rounded shadow'
32
+ <<~END_IMG
33
+ <img #{@props.attr_alt}
34
+ class="imgImg #{img_classes.squish}"
35
+ src="#{@source.src_fallback}"
36
+ #{@props.attr_style_img}
37
+ #{@props.attr_title}
38
+ />
39
+ END_IMG
40
+ end
41
+
42
+ # See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture
43
+ def generate_picture
44
+ return generate_img if @props.src.start_with? 'http'
45
+
46
+ # avif is not well supported yet
47
+ # <source srcset="#{@props.src_any 'avif'}" type="image/avif">
48
+ result = <<~END_IMG
49
+ <picture#{@props.attr_id} class='imgPicture'>
50
+ #{@source.generate.join("\n ")}
51
+ #{generate_img}
52
+ </picture>
53
+ END_IMG
54
+ result.strip
55
+ end
56
+
57
+ def generate_url_caption
58
+ <<~END_URL
59
+ <a href="#{@props.url}"#{@props.attr_target}#{@props.attr_nofollow}>
60
+ #{@props.caption}
61
+ </a>
62
+ END_URL
18
63
  end
19
64
 
20
- private
65
+ def generate_url_wrapper
66
+ <<~END_HTML
67
+ <a href='#{@props.url}'#{@props.attr_target}#{@props.attr_nofollow} class='imgImgUrl'>
68
+ #{generate_picture}
69
+ </a>
70
+ END_HTML
71
+ end
21
72
 
22
73
  def generate_wrapper
23
74
  classes = "imgWrapper #{@props.img_display} #{@props.align} #{@props.attr_size_class} #{@props.wrapper_class}".squish
24
- result = <<~END_HTML
75
+ <<~END_HTML.remove_blank_lines
25
76
  <div class='#{classes}' style='#{@props.attr_width_style} #{@props.wrapper_style}'>
26
77
  #{"<figure>\n" if @props.caption}
27
- #{ if @props.url
28
- "<a href='#{@props.url}'#{@props.attr_target}#{@props.attr_nofollow} class='imgImgUrl'>#{generate_img}</a>"
29
- else
30
- generate_img
31
- end
32
- }
33
- #{generate_figure_caption}
78
+ #{@props.url ? generate_url_wrapper : generate_picture}
79
+ #{generate_figcaption if @props.caption}
34
80
  #{"</figure>\n" if @props.caption}
35
81
  #{@props.attribute if @props.attribution}
36
82
  </div>
37
83
  END_HTML
38
- result.strip
39
84
  end
40
85
 
41
- def generate_figure_caption
42
- return nil unless @props.caption
43
-
44
- <<~END_CAPTION
45
- <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
- }
56
- </figcaption>
57
- END_CAPTION
58
- end
59
-
60
- # See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture
61
- def generate_img
62
- img_classes = @props.classes || 'rounded shadow'
63
- <<~END_IMG
64
- <picture#{@props.attr_id} class='imgPicture'>
65
- <source srcset="#{@props.src_any 'svg'}" type="image/svg">
66
- <!---<source srcset="#{@props.src_any 'avif'}" type="image/avif">-->
67
- <source srcset="#{@props.src}" type="image/webp">
68
- <source srcset="#{@props.src_any 'apng'}" type="image/apng">
69
- <source srcset="#{@props.src_any 'png'}" type="image/png">
70
- <source srcset="#{@props.src_any 'jpg'}" type="image/jpeg">
71
- <source srcset="#{@props.src_any 'jpeg'}" type="image/jpeg">
72
- <source srcset="#{@props.src_any 'jfif'}" type="image/jpeg">
73
- <source srcset="#{@props.src_any 'pjpeg'}" type="image/jpeg">
74
- <source srcset="#{@props.src_any 'pjp'}" type="image/jpeg">
75
- <source srcset="#{@props.src_any 'gif'}" type="image/gif">
76
- <source srcset="#{@props.src_any 'tif'}" type="image/tiff">
77
- <source srcset="#{@props.src_any 'tiff'}" type="image/tiff">
78
- <source srcset="#{@props.src_any 'bmp'}" type="image/bmp">
79
- <source srcset="#{@props.src_any 'ico'}" type="image/x-icon">
80
- <source srcset="#{@props.src_any 'cur'}" type="image/x-icon">
81
- <img #{@props.attr_alt}
82
- class="imgImg #{img_classes.squish}"
83
- src="#{@props.src_png}"
84
- #{@props.attr_style_img}
85
- #{@props.attr_title}
86
- />
87
- </picture>
88
- END_IMG
86
+ def to_s
87
+ @props.compute_dependant_properties
88
+ generate_wrapper
89
89
  end
90
90
  end
data/lib/img_props.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'uri'
2
+
1
3
  # Properties from user
2
4
  # All methods are idempotent.
3
5
  # attr_ methods can be called after compute_dependant_properties
@@ -8,6 +10,7 @@ class ImgProperties
8
10
  :url, :wrapper_class, :wrapper_style
9
11
 
10
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
11
14
 
12
15
  def attr_alt
13
16
  "alt='#{@alt}'" if @alt
@@ -67,13 +70,7 @@ class ImgProperties
67
70
  end
68
71
 
69
72
  def src_any(filetype)
70
- @src.gsub('.webp', ".#{filetype}")
71
- end
72
-
73
- def src_png
74
- raise Jekyll::ImgError, "The 'src' parameter was not specified" if @src.to_s.empty?
75
-
76
- @src.gsub('.webp', '.png')
73
+ @src.gsub(/\..*?$/, ".#{filetype}")
77
74
  end
78
75
 
79
76
  def self.local_path?(src)
@@ -84,7 +81,7 @@ class ImgProperties
84
81
  private
85
82
 
86
83
  def setup_src
87
- 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)
88
85
 
89
86
  raise Jekyll::ImgError, "The 'src' parameter was empty" if @src.empty?
90
87
 
@@ -101,8 +98,6 @@ class ImgProperties
101
98
  # raise Jekyll::ImgError, "#{@src} does not exist" unless File.exist?(src)
102
99
  end
103
100
 
104
- 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
105
-
106
101
  def size_unit_specified?
107
102
  return false if @size == false || @size.to_s.strip.empty?
108
103
 
@@ -1,3 +1,3 @@
1
1
  module JekyllImgVersion
2
- VERSION = '0.2.5'.freeze
2
+ VERSION = '0.2.7'.freeze
3
3
  end
data/lib/jekyll_img.rb CHANGED
@@ -3,17 +3,18 @@ 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
9
10
  # @license SPDX-License-Identifier: Apache-2.0
10
11
 
11
12
  module ImgModule
12
- PLUGIN_NAME = 'img'.freeze
13
+ PLUGIN_NAME = 'img'.freeze unless const_defined?(:PLUGIN_NAME)
13
14
  end
14
15
 
15
16
  module Jekyll
16
- ImgError = ::JekyllSupport.define_error
17
+ ImgError = ::JekyllSupport.define_error unless const_defined?(:ImgError)
17
18
 
18
19
  # Plugin implementation
19
20
  class Img < ::JekyllSupport::JekyllTag
@@ -54,6 +55,6 @@ module Jekyll
54
55
  e.html_message
55
56
  end
56
57
 
57
- ::JekyllSupport::JekyllPluginHelper.register(self, ImgModule::PLUGIN_NAME)
58
+ ::JekyllSupport::JekyllPluginHelper.register(self, ImgModule::PLUGIN_NAME) unless $PROGRAM_NAME.end_with?('/rspec')
58
59
  end
59
60
  end
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,36 +1,69 @@
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
9
+ Dir.chdir("demo")
10
+ props = ImgProperties.new
11
+ props.src = '/assets/images/jekyll.webp'
12
+ builder = described_class.new(props)
13
+
14
+ it 'generates sources' do
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)
44
+ end
45
+
8
46
  it 'generates a default img' do
9
- props = ImgProperties.new
10
- props.src = 'blah.webp'
11
- builder = described_class.new(props)
12
- picture = <<~END_IMG
47
+ desired = <<~END_IMG
13
48
  <div class='imgWrapper imgFlex' style=' '>
14
49
  <picture class='imgPicture'>
15
- <source srcset="/assets/images/blah.webp" type="image/webp">
16
- <source srcset="/assets/images/blah.png" type="image/png">
50
+ <source srcset="/assets/images/jekyll.webp" type="image/webp">
51
+ <source srcset="/assets/images/jekyll.png" type="image/png">
17
52
  <img class="imgImg rounded shadow"
18
- src="/assets/images/blah.png"
53
+ src="/assets/images/jekyll.png"
19
54
  style='width: 100%; '
20
55
  />
21
56
  </picture>
22
57
  </div>
23
58
  END_IMG
24
59
 
25
- expect(builder.send(:generate_figure_caption)).to be_nil
26
- expect(builder.send(:generate_wrapper)).to match_ignoring_whitespace(picture)
60
+ actual = builder.generate_wrapper
61
+ expect(actual).to match_ignoring_whitespace(desired)
27
62
  end
28
63
 
29
- it 'generates an img with size and caption' do
30
- props = ImgProperties.new
64
+ it 'generates an img wrapper with size and caption' do
31
65
  props.caption = 'This is a caption'
32
66
  props.size = '123px'
33
- props.src = 'blah.webp'
34
67
  builder = described_class.new(props)
35
68
 
36
69
  caption = <<~END_CAPTION
@@ -39,15 +72,15 @@ class ImgPropertiesTest
39
72
  </figcaption>
40
73
  END_CAPTION
41
74
 
42
- picture = <<~END_IMG
75
+ desired = <<~END_IMG
43
76
  <div class='imgWrapper imgBlock' style='width: 123px; '>
44
77
  <figure>
45
78
  <picture class='imgPicture'>
46
- <source srcset="/assets/images/blah.webp" type="image/webp">
47
- <source srcset="/assets/images/blah.png" type="image/png">
79
+ <source srcset="/assets/images/jekyll.webp" type="image/webp">
80
+ <source srcset="/assets/images/jekyll.png" type="image/png">
48
81
  <img alt='This is a caption'
49
82
  class="imgImg rounded shadow"
50
- src="/assets/images/blah.png"
83
+ src="/assets/images/jekyll.png"
51
84
  style='width: 100%; '
52
85
  title='This is a caption'
53
86
  />
@@ -57,8 +90,8 @@ class ImgPropertiesTest
57
90
  </div>
58
91
  END_IMG
59
92
 
60
- expect(builder.send(:generate_figure_caption)).to match_ignoring_whitespace(caption)
61
- expect(builder.send(:generate_wrapper)).to match_ignoring_whitespace(picture)
93
+ actual = builder.generate_wrapper
94
+ expect(actual).to match_ignoring_whitespace(desired)
62
95
  end
63
96
  end
64
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
@@ -26,15 +26,19 @@ class ImgProperitesTest
26
26
  expect(props.attr_target).to eq(" target='_blank'")
27
27
  expect(props.attr_title).to be_nil
28
28
  expect(props.attr_width_style).to be_nil
29
-
30
- props.compute_dependant_properties
31
- expect(props.attr_wrapper_align_class).to eq('inline')
32
29
  end
33
30
 
31
+ # it 'defaults to inline alignment' do
32
+ # props = described_class.new
33
+ # props.src = 'relative/path.webp'
34
+ # props.compute_dependant_properties
35
+ # expect(props.attr_wrapper_align_class).to eq('inline')
36
+ # end
37
+
34
38
  it 'raises exception if src was not specified' do
35
39
  props = described_class.new
36
- expect { props.src_png }.to raise_error(SystemExit)
37
- expect { props.send(:setup_src) }.to raise_error(SystemExit)
40
+ expect { props.compute_dependant_properties }.to raise_error(Jekyll::ImgError)
41
+ expect { props.send(:setup_src) }.to raise_error(Jekyll::ImgError)
38
42
 
39
43
  props.src = 'relative/path.webp'
40
44
  props.send(:setup_src)
@@ -69,21 +73,18 @@ class ImgProperitesTest
69
73
 
70
74
  props.size = '100px'
71
75
  expect(props.attr_size_class).to be_nil
72
- expect(props.attr_style_img).to eq("style='max-width: 100px;'")
76
+ expect(props.attr_style_img).to eq("style='width: 100%; '")
73
77
  expect(props.attr_width_style).to eq('width: 100px;')
74
78
 
75
79
  props.size = '10%'
76
80
  expect(props.attr_size_class).to be_nil
77
- expect(props.attr_style_img).to eq("style='max-width: 10%;'")
78
81
  expect(props.attr_width_style).to eq('width: 10%;')
82
+ expect(props.attr_style_img).to eq("style='width: 100%; '")
79
83
 
80
84
  props.size = 'fullsize'
81
85
  expect(props.attr_size_class).to eq('fullsize')
82
86
  expect(props.attr_width_style).to be_nil
83
87
 
84
- props.style = 'width: 30rem;'
85
- expect(props.attr_style_img).to eq("style='width: 30rem;'")
86
-
87
88
  props.target = 'moon'
88
89
  expect(props.attr_target).to eq(" target='moon'")
89
90
 
@@ -95,17 +96,5 @@ class ImgProperitesTest
95
96
  expect(props.attr_size_class).to be_nil
96
97
  expect(props.attr_width_style).to eq('width: 100px;')
97
98
  end
98
-
99
- it 'generates proper alignment attributes' do
100
- props = described_class.new
101
-
102
- props.align = 'inline'
103
- props.compute_dependant_properties
104
- expect(props.attr_wrapper_align_class).to eq('inline')
105
-
106
- props.align = 'center'
107
- props.compute_dependant_properties
108
- expect(props.attr_wrapper_align_class).to eq('center')
109
- end
110
99
  end
111
100
  end
@@ -1,9 +1,11 @@
1
1
  require 'jekyll'
2
2
  require 'jekyll_plugin_logger'
3
+ require 'helper/jekyll_plugin_helper'
4
+ require 'jekyll_plugin_support'
3
5
  require 'rspec/match_ignoring_whitespace'
4
6
  require_relative '../lib/jekyll_img'
5
7
 
6
- Registers = Struct.new(:page, :site)
8
+ Registers = Struct.new(:page, :site) unless defined? :Registers
7
9
 
8
10
  # Mock for Collections
9
11
  class Collections
@@ -46,14 +48,15 @@ class MyTest
46
48
  let(:parse_context) { TestParseContext.new }
47
49
 
48
50
  let(:helper) do
49
- JekyllPluginHelper.new(
51
+ ::JekyllSupport::JekyllPluginHelper.new(
50
52
  'img',
51
53
  'src="./blah.webp"',
52
- logger
54
+ logger,
55
+ false
53
56
  )
54
57
  end
55
58
 
56
- it 'has no cite or url' do
59
+ xit 'has no cite or url' do
57
60
  helper.reinitialize('src="./blah.webp"')
58
61
  img = described_class.send(
59
62
  :new,
@@ -61,10 +64,11 @@ class MyTest
61
64
  helper.markup.dup,
62
65
  parse_context
63
66
  )
64
- result = img.send(:render_impl, helper.markup)
65
- expect(result).to match_ignoring_whitespace <<-END_RESULT
67
+ actual = img.render_impl
68
+ desired = <<~END_DESIRED
66
69
  <img src="./blah.webp">
67
- END_RESULT
70
+ END_DESIRED
71
+ expect(actual).to match_ignoring_whitespace(desired)
68
72
  end
69
73
  end
70
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
@@ -0,0 +1,16 @@
1
+ example_id | status | run_time |
2
+ ------------------------------- | ------ | --------------- |
3
+ ./spec/img_builder_spec.rb[1:1] | failed | 14.37 seconds |
4
+ ./spec/img_builder_spec.rb[1:2] | failed | 0.01498 seconds |
5
+ ./spec/img_builder_spec.rb[1:3] | failed | 0.00093 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,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll_img
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Slinn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-20 00:00:00.000000000 Z
11
+ date: 2024-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -55,10 +55,13 @@ files:
55
55
  - lib/img_props.rb
56
56
  - lib/jekyll_img.rb
57
57
  - lib/jekyll_img/version.rb
58
+ - lib/source.rb
58
59
  - spec/img_builder_spec.rb
59
60
  - spec/img_props_spec.rb
60
61
  - spec/jekyll_img_spec.rb
62
+ - spec/source_spec.rb
61
63
  - spec/spec_helper.rb
64
+ - spec/status_persistence.txt
62
65
  homepage: https://www.mslinn.com/jekyll_plugins/jekyll_img.html
63
66
  licenses:
64
67
  - MIT
@@ -94,5 +97,7 @@ test_files:
94
97
  - spec/img_builder_spec.rb
95
98
  - spec/img_props_spec.rb
96
99
  - spec/jekyll_img_spec.rb
100
+ - spec/source_spec.rb
97
101
  - spec/spec_helper.rb
102
+ - spec/status_persistence.txt
98
103
  ...