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 +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +63 -36
- data/lib/img_builder.rb +62 -62
- data/lib/img_props.rb +5 -10
- data/lib/jekyll_img/version.rb +1 -1
- data/lib/jekyll_img.rb +4 -3
- data/lib/source.rb +98 -0
- data/spec/img_builder_spec.rb +51 -18
- data/spec/img_props_spec.rb +12 -23
- data/spec/jekyll_img_spec.rb +11 -7
- data/spec/source_spec.rb +87 -0
- data/spec/status_persistence.txt +16 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ec131406e5dce078a0d63a5a821f73b8de66ece127990a8c3fa34a348c9d819
|
4
|
+
data.tar.gz: ed9c9f00d0df3b50ea9409593ccc58fa6aca91d2e8c200a4ece28a8b3fc21aa3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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’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
|
-
|
31
|
-
|
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
|
-
|
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
|
-
|
37
|
-
|
38
|
-
`
|
39
|
-
and
|
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
|
-
|
45
|
-
|
54
|
+
<picture>
|
55
|
+
<source srcset="blah.png" />
|
56
|
+
<source srcset="blah.jpg" />
|
57
|
+
<img src="blah.webp" />
|
58
|
+
</picture>
|
46
59
|
```
|
47
60
|
|
48
|
-
|
49
|
-
|
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
|
-
|
53
|
-
|
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:
|
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
|
16
|
-
|
17
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#{
|
28
|
-
|
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
|
42
|
-
|
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(
|
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
|
|
data/lib/jekyll_img/version.rb
CHANGED
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
|
data/spec/img_builder_spec.rb
CHANGED
@@ -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
|
-
|
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/
|
16
|
-
<source srcset="/assets/images/
|
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/
|
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
|
-
|
26
|
-
expect(
|
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
|
-
|
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/
|
47
|
-
<source srcset="/assets/images/
|
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/
|
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
|
-
|
61
|
-
expect(
|
93
|
+
actual = builder.generate_wrapper
|
94
|
+
expect(actual).to match_ignoring_whitespace(desired)
|
62
95
|
end
|
63
96
|
end
|
64
97
|
end
|
data/spec/img_props_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require_relative '../lib/img_props'
|
2
2
|
|
3
|
-
class
|
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.
|
37
|
-
expect { props.send(:setup_src) }.to raise_error(
|
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='
|
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
|
data/spec/jekyll_img_spec.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
65
|
-
|
67
|
+
actual = img.render_impl
|
68
|
+
desired = <<~END_DESIRED
|
66
69
|
<img src="./blah.webp">
|
67
|
-
|
70
|
+
END_DESIRED
|
71
|
+
expect(actual).to match_ignoring_whitespace(desired)
|
68
72
|
end
|
69
73
|
end
|
70
74
|
end
|
data/spec/source_spec.rb
ADDED
@@ -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.
|
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-
|
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
|
...
|