jekyll_img 0.2.5 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
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
  ...