@thulite/images 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,283 @@
1
+ {{- /* Based on https://www.veriphor.com/articles/link-and-image-render-hooks/#image-render-hook */}}
2
+
3
+ {{- /* Last modified: 2023-09-05T11:48:34-07:00 */}}
4
+
5
+ {{- /*
6
+ Copyright 2023 Veriphor LLC
7
+
8
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
9
+ use this file except in compliance with the License. You may obtain a copy of
10
+ the License at
11
+
12
+ https://www.apache.org/licenses/LICENSE-2.0
13
+
14
+ Unless required by applicable law or agreed to in writing, software
15
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17
+ License for the specific language governing permissions and limitations under
18
+ the License.
19
+ */}}
20
+
21
+ {{- /*
22
+ Renders an HTML img element, in multiple formats and sizes.
23
+
24
+ It resolves internal destinations by looking for a matching:
25
+
26
+ 1. Page resource (an image in the current page bundle)
27
+ 2. Section resource (an image in the current section)
28
+ 3. Global resource (an image in the assets directory)
29
+
30
+ It skips the section resource lookup if the current page is a leaf bundle, and
31
+ captures external destinations as resources for local hosting. The build will
32
+ fail if this partial is unable to resolve a destination.
33
+
34
+ You must place global resources in the assets directory. If you have placed
35
+ your resources in the static directory, and you are unable or unwilling to move
36
+ them, you must mount the static directory to the assets directory by including
37
+ both of these entries in your site configuration:
38
+
39
+ [[module.mounts]]
40
+ source = 'assets'
41
+ target = 'assets'
42
+
43
+ [[module.mounts]]
44
+ source = 'static'
45
+ target = 'assets'
46
+
47
+ Add this CSS to your site to enable responsive image behavior:
48
+
49
+ img {
50
+ height: auto;
51
+ max-width: 100%;
52
+ }
53
+
54
+ Add this CSS to your site to remove small gaps between adjacent elements:
55
+
56
+ img, picture {
57
+ font-size: 0;
58
+ }
59
+
60
+ @context {page} [page] The current page.
61
+ @context {string} [src] The path to the base image: a page resource, a global resource, or a remote resource.
62
+ @contect {int} [width] The display width of the image, in pixels, falling back to 100% of the viewport width.
63
+ @context {string} [sizes] = "" # "100vw", "75vw", or "auto" for example
64
+ @context {string slice} [formats] A slice of image formats, ordered by precedence, to use when creating images for the srcset attribute of each source element.
65
+ @context {string} [process] = "" # "fill 1600x900" for example
66
+ @context {string} [lqip] = "" # "16x webp q20" or "21x webp q20" for example
67
+ @context {string} [decoding] The img element's decoding attribute.
68
+ @context {string} [fetchpriority] The img element's fetchpriority attribute.
69
+ @context {string} [loading] The img element's loading attribute.
70
+ @context {string} [alt] The img element's alt attribute.
71
+ @context {string} [title] The img element's title attribute.
72
+ @context {string} [class] The img element's class attribute.
73
+
74
+ @returns {template.HTML}
75
+
76
+ @example (required args only)
77
+
78
+ {{- partial "img.html" (dict "page" . "src" "images/zion.jpg") }}
79
+
80
+ @example (all args)
81
+ {{- $opts := dict
82
+ "page" .
83
+ "src" "images/bryce-canyon-national-park.jpg"
84
+ "width" 768
85
+ "sizes" "auto"
86
+ "formats" (slice "webp" "jpeg")
87
+ "process" "fill 1600x900"
88
+ "lqip" "16x webp q20"
89
+ "decoding" "async"
90
+ "fetchpriority" "auto"
91
+ "loading" "eager"
92
+ "alt" "Bryce Canyon National Park"
93
+ "title" "A beautiful day in Bryce Canyon National Park"
94
+ "class" "foo"
95
+ }}
96
+ {{- partial "img.html" $opts }}
97
+
98
+ */}}
99
+
100
+ {{- /* Initialize. */}}
101
+ {{- $partialName := "img" }}
102
+
103
+ {{- /* Verify minimum required version. */}}
104
+ {{- $minHugoVersion := "0.118.0" }}
105
+ {{- if lt hugo.Version $minHugoVersion }}
106
+ {{- errorf "The %q partial requires Hugo v%s or later." $partialName $minHugoVersion }}
107
+ {{- end }}
108
+
109
+ {{- /* Validate page arg. */}}
110
+ {{- if not .page }}
111
+ {{- errorf "The %q partial requires a page argument." $partialName }}
112
+ {{- end }}
113
+
114
+ {{- /* Determine content path for warning and error messages. */}}
115
+ {{- $contentPath := "" }}
116
+ {{- with .page.File }}
117
+ {{- $contentPath = .Path }}
118
+ {{- else }}
119
+ {{- $contentPath = .Path }}
120
+ {{- end }}
121
+
122
+ {{- /* Set defaults and get args. */}}
123
+ {{- $alt := or .alt "" }}
124
+ {{- $class := or .class "" }}
125
+ {{- $formats := or .formats (slice "webp") }}
126
+ {{- $decoding := or .decoding site.Params.thulite_images.defaults.decoding }}
127
+ {{- $fetchPriority := or .fetchpriority site.Params.thulite_images.defaults.fetchpriority }}
128
+ {{- $loading := or .loading site.Params.thulite_images.defaults.loading }}
129
+ {{- $process := or .process site.Params.thulite_images.defaults.process }}
130
+ {{- $lqip := or .lqip site.Params.thulite_images.defaults.lqip }}
131
+ {{- $src := or .src "" }}
132
+ {{- $title := or .title "" }}
133
+ {{- $width := or (int .width) 0 }}
134
+ {{- $fallbackFormat := "jpeg" }}
135
+ {{- $stdWidths := site.Params.thulite_images.defaults.widths }}
136
+ {{- $stdSizes := or .sizes site.Params.thulite_images.defaults.sizes }}
137
+
138
+ {{- /* Validate args. */}}
139
+ {{- $validFormats := slice "gif" "jpg" "jpeg" "png" "webp"}}
140
+ {{- if reflect.IsSlice $formats }}
141
+ {{- $formats = apply $formats "strings.ToLower" "." }}
142
+ {{- range $formats }}
143
+ {{- if not (in $validFormats .) }}
144
+ {{- errorf "The formats argument passed to the %q partial is invalid. Valid formats are %s. See %s" $partialName (delimit $validFormats ", " ", and ") $contentPath }}
145
+ {{- end }}
146
+ {{- end }}
147
+ {{- else }}
148
+ {{- errorf "The formats argument passed to the %q partial is not a slice. See %s" $partialName $contentPath }}
149
+ {{- end }}
150
+
151
+ {{- if not $src }}
152
+ {{- errorf "The %q partial requires an image path, relative to the assets directory. See %s" $partialName $contentPath }}
153
+ {{- end }}
154
+
155
+ {{- /* Capture image as a resource. */}}
156
+ {{- $r := "" }}
157
+ {{- $ctx := dict
158
+ "page" .page
159
+ "path" $src
160
+ "partialName" $partialName
161
+ "contentPath" $contentPath
162
+ }}
163
+ {{- with partial "inline/capture-resource.html" $ctx }}
164
+ {{- $r = . }}
165
+ {{- end }}
166
+
167
+ {{- /* Process image. */}}
168
+ {{- with $process }}
169
+ {{- $r = $r.Process $process }}
170
+ {{- end }}
171
+
172
+ {{- /* Process LQIP. */}}
173
+ {{- $l := "" }}
174
+ {{- with $lqip }}
175
+ {{- $l = $r.Resize . }}
176
+ {{- end }}
177
+
178
+ {{- /* Determine widths for srcset generation. */}}
179
+ {{- $widths := slice }}
180
+ {{- if $width }}
181
+ {{- /* The width was specified; generate 1x, 2x, 3x, and 4x images. */}}
182
+ {{- $widths = slice $r.Width }}
183
+ {{- range seq 4 }}
184
+ {{- with mul . $width }}
185
+ {{- if and (le . $r.Width) (le . (math.Max $stdWidths)) }}
186
+ {{- /* Do not enlarge, and do not exceed maximum of $stdWidths. */}}
187
+ {{- $widths = $widths | append . }}
188
+ {{- end }}
189
+ {{- end }}
190
+ {{- end }}
191
+ {{- else }}
192
+ {{- /* The width was not speficied, will be using $stdWidths. */}}
193
+ {{- $stdWidths = $stdWidths | append $r.Width | sort }}
194
+ {{- range $stdWidths }}
195
+ {{- /* Do not enlarge. */}}
196
+ {{- if (le . $r.Width) }}
197
+ {{- $widths = $widths | append . }}
198
+ {{- end }}
199
+ {{- end }}
200
+ {{- end }}
201
+ {{- $widths = $widths | uniq | sort}}
202
+
203
+ {{- /* Create fallback image (fi) with the smallest of widths. */}}
204
+ {{- $fi := $r.Resize (printf "%dx %s" (math.Min $widths | int) $fallbackFormat) }}
205
+
206
+ {{- /* Create the image map. */}}
207
+ {{- $im := dict }}
208
+ {{- range $format := $formats }}
209
+ {{- $sizes := slice }}
210
+ {{- range sort $widths }}
211
+ {{- $sizes = $sizes | append ($r.Resize (printf "%dx %s" . $format)) }}
212
+ {{- end }}
213
+ {{- $im = merge $im (dict $format $sizes) }}
214
+ {{- end }}
215
+
216
+ {{- /* Render. */}}
217
+ <img
218
+ srcset="data:{{ $l.MediaType }};base64,{{ $l.Content | base64Encode }}"
219
+ {{- range $formats }}
220
+ {{- with index $im . }}
221
+ {{- $sizes := $stdSizes }}
222
+ {{- with $width }}
223
+ {{- $sizes = printf "%dpx" . }}
224
+ {{- end }}
225
+ data-srcset="
226
+ {{- range $k, $_ := . }}
227
+ {{- if $k }},{{- end }}
228
+ {{- printf `%s %dw` .RelPermalink .Width }}
229
+ {{- end }}"
230
+ data-sizes="{{ $stdSizes }}"
231
+ {{- end }}
232
+ {{- end }}
233
+ src="{{ $fi.RelPermalink }}"
234
+ width="{{ string $r.Width }}"
235
+ height="{{ string $r.Height }}"
236
+ decoding="{{ $decoding }}"
237
+ fetchpriority="{{ $fetchPriority }}"
238
+ loading="{{ $loading }}"
239
+ alt="{{ $alt }}"
240
+ {{- with .title }}title="{{ $title }}"{{- end }}
241
+ class="lazyload blur-up{{- with .class }} {{ . }}{{- end }}"
242
+ >
243
+
244
+ {{- define "partials/inline/capture-resource.html" }}
245
+ {{- /* Parse destination. */}}
246
+ {{- $u := urls.Parse .path }}
247
+
248
+ {{- /* Set common message. */}}
249
+ {{- $msg := printf "The %q partial was unable to get %q in %s" .partialName $u.String .contentPath }}
250
+
251
+ {{- /* Get image resource. */}}
252
+ {{- $r := "" }}
253
+ {{- if $u.IsAbs }}
254
+ {{- with resources.GetRemote $u.String }}
255
+ {{- with .Err }}
256
+ {{- errorf "%s. See %s" . $.contentPath }}
257
+ {{- else }}
258
+ {{- /* Destination is a remote resource. */}}
259
+ {{- $r = . }}
260
+ {{- end }}
261
+ {{- else }}
262
+ {{- errorf $msg }}
263
+ {{- end }}
264
+ {{- else }}
265
+ {{- with .page.Resources.Get (strings.TrimPrefix "./" $u.Path) }}
266
+ {{- /* Destination is a page resource. */}}
267
+ {{- $r = . }}
268
+ {{- else }}
269
+ {{- with (and (ne .page.BundleType "leaf") (.page.CurrentSection.Resources.Get (strings.TrimPrefix "./" $u.Path)) ) }}
270
+ {{- /* Destination is a section resource, and current page is not a leaf bundle. */}}
271
+ {{- $r = . }}
272
+ {{- else }}
273
+ {{- with resources.Get $u.Path }}
274
+ {{- /* Destination is a global resource. */}}
275
+ {{- $r = . }}
276
+ {{- else }}
277
+ {{- errorf $msg }}
278
+ {{- end }}
279
+ {{- end }}
280
+ {{- end }}
281
+ {{- end }}
282
+ {{- return $r }}
283
+ {{- end -}}
@@ -0,0 +1,285 @@
1
+ {{- /* Based on https://www.veriphor.com/articles/link-and-image-render-hooks/#image-render-hook */}}
2
+
3
+ {{- /* Last modified: 2023-09-05T11:48:34-07:00 */}}
4
+
5
+ {{- /*
6
+ Copyright 2023 Veriphor LLC
7
+
8
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
9
+ use this file except in compliance with the License. You may obtain a copy of
10
+ the License at
11
+
12
+ https://www.apache.org/licenses/LICENSE-2.0
13
+
14
+ Unless required by applicable law or agreed to in writing, software
15
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17
+ License for the specific language governing permissions and limitations under
18
+ the License.
19
+ */}}
20
+
21
+ {{- /*
22
+ Renders an HTML picture element, in multiple formats and sizes.
23
+
24
+ It resolves internal destinations by looking for a matching:
25
+
26
+ 1. Page resource (an image in the current page bundle)
27
+ 2. Section resource (an image in the current section)
28
+ 3. Global resource (an image in the assets directory)
29
+
30
+ It skips the section resource lookup if the current page is a leaf bundle, and
31
+ captures external destinations as resources for local hosting. The build will
32
+ fail if this partial is unable to resolve a destination.
33
+
34
+ You must place global resources in the assets directory. If you have placed
35
+ your resources in the static directory, and you are unable or unwilling to move
36
+ them, you must mount the static directory to the assets directory by including
37
+ both of these entries in your site configuration:
38
+
39
+ [[module.mounts]]
40
+ source = 'assets'
41
+ target = 'assets'
42
+
43
+ [[module.mounts]]
44
+ source = 'static'
45
+ target = 'assets'
46
+
47
+ Add this CSS to your site to enable responsive image behavior:
48
+
49
+ img {
50
+ height: auto;
51
+ max-width: 100%;
52
+ }
53
+
54
+ Add this CSS to your site to remove small gaps between adjacent elements:
55
+
56
+ img, picture {
57
+ font-size: 0;
58
+ }
59
+
60
+ @context {page} [page] The current page.
61
+ @context {string} [src] The path to the base image: a page resource, a global resource, or a remote resource.
62
+ @contect {int} [width] The display width of the image, in pixels, falling back to 100% of the viewport width.
63
+ @context {string} [sizes] = "" # "100vw", "75vw", or "auto" for example
64
+ @context {string slice} [formats] A slice of image formats, ordered by precedence, to use when creating images for the srcset attribute of each source element.
65
+ @context {string} [process] = "" # "fill 1600x900" for example
66
+ @context {string} [lqip] = "" # "16x webp q20" or "21x webp q20" for example
67
+ @context {string} [decoding] The img element's decoding attribute.
68
+ @context {string} [fetchpriority] The img element's fetchpriority attribute.
69
+ @context {string} [loading] The img element's loading attribute.
70
+ @context {string} [alt] The img element's alt attribute.
71
+ @context {string} [title] The img element's title attribute.
72
+ @context {string} [class] The img element's class attribute.
73
+
74
+ @returns {template.HTML}
75
+
76
+ @example (required args only)
77
+
78
+ {{- partial "picture.html" (dict "page" . "src" "images/zion.jpg") }}
79
+
80
+ @example (all args)
81
+ {{- $opts := dict
82
+ "page" .
83
+ "src" "images/bryce-canyon-national-park.jpg"
84
+ "width" 768
85
+ "sizes" "auto"
86
+ "formats" (slice "webp" "jpeg")
87
+ "process" "fill 1600x900"
88
+ "lqip" "16x webp q20"
89
+ "decoding" "async"
90
+ "fetchpriority" "auto"
91
+ "loading" "eager"
92
+ "alt" "Bryce Canyon National Park"
93
+ "title" "A beautiful day in Bryce Canyon National Park"
94
+ "class" "foo"
95
+ }}
96
+ {{- partial "picture.html" $opts }}
97
+
98
+ */}}
99
+
100
+ {{- /* Initialize. */}}
101
+ {{- $partialName := "picture" }}
102
+
103
+ {{- /* Verify minimum required version. */}}
104
+ {{- $minHugoVersion := "0.118.0" }}
105
+ {{- if lt hugo.Version $minHugoVersion }}
106
+ {{- errorf "The %q partial requires Hugo v%s or later." $partialName $minHugoVersion }}
107
+ {{- end }}
108
+
109
+ {{- /* Validate page arg. */}}
110
+ {{- if not .page }}
111
+ {{- errorf "The %q partial requires a page argument." $partialName }}
112
+ {{- end }}
113
+
114
+ {{- /* Determine content path for warning and error messages. */}}
115
+ {{- $contentPath := "" }}
116
+ {{- with .page.File }}
117
+ {{- $contentPath = .Path }}
118
+ {{- else }}
119
+ {{- $contentPath = .Path }}
120
+ {{- end }}
121
+
122
+ {{- /* Set defaults and get args. */}}
123
+ {{- $alt := or .alt "" }}
124
+ {{- $class := or .class "" }}
125
+ {{- $formats := or .formats (slice "webp") }}
126
+ {{- $decoding := or .decoding site.Params.thulite_images.defaults.decoding }}
127
+ {{- $fetchPriority := or .fetchpriority site.Params.thulite_images.defaults.fetchpriority }}
128
+ {{- $loading := or .loading site.Params.thulite_images.defaults.loading }}
129
+ {{- $process := or .process site.Params.thulite_images.defaults.process }}
130
+ {{- $lqip := or .lqip site.Params.thulite_images.defaults.lqip }}
131
+ {{- $src := or .src "" }}
132
+ {{- $title := or .title "" }}
133
+ {{- $width := or (int .width) 0 }}
134
+ {{- $fallbackFormat := "jpeg" }}
135
+ {{- $stdWidths := site.Params.thulite_images.defaults.widths }}
136
+ {{- $stdSizes := or .sizes site.Params.thulite_images.defaults.sizes }}
137
+
138
+ {{- /* Validate args. */}}
139
+ {{- $validFormats := slice "gif" "jpg" "jpeg" "png" "webp"}}
140
+ {{- if reflect.IsSlice $formats }}
141
+ {{- $formats = apply $formats "strings.ToLower" "." }}
142
+ {{- range $formats }}
143
+ {{- if not (in $validFormats .) }}
144
+ {{- errorf "The formats argument passed to the %q partial is invalid. Valid formats are %s. See %s" $partialName (delimit $validFormats ", " ", and ") $contentPath }}
145
+ {{- end }}
146
+ {{- end }}
147
+ {{- else }}
148
+ {{- errorf "The formats argument passed to the %q partial is not a slice. See %s" $partialName $contentPath }}
149
+ {{- end }}
150
+
151
+ {{- if not $src }}
152
+ {{- errorf "The %q partial requires an image path, relative to the assets directory. See %s" $partialName $contentPath }}
153
+ {{- end }}
154
+
155
+ {{- /* Capture image as a resource. */}}
156
+ {{- $r := "" }}
157
+ {{- $ctx := dict
158
+ "page" .page
159
+ "path" $src
160
+ "partialName" $partialName
161
+ "contentPath" $contentPath
162
+ }}
163
+ {{- with partial "inline/capture-resource.html" $ctx }}
164
+ {{- $r = . }}
165
+ {{- end }}
166
+
167
+ {{- /* Process image. */}}
168
+ {{- with $process }}
169
+ {{- $r = $r.Process $process }}
170
+ {{- end }}
171
+
172
+ {{- /* Process LQIP. */}}
173
+ {{- $l := "" }}
174
+ {{- with $lqip }}
175
+ {{- $l = $r.Resize . }}
176
+ {{- end }}
177
+
178
+ {{- /* Determine widths for srcset generation. */}}
179
+ {{- $widths := slice }}
180
+ {{- if $width }}
181
+ {{- /* The width was specified; generate 1x, 2x, 3x, and 4x images. */}}
182
+ {{- $widths = slice $r.Width }}
183
+ {{- range seq 4 }}
184
+ {{- with mul . $width }}
185
+ {{- if and (le . $r.Width) (le . (math.Max $stdWidths)) }}
186
+ {{- /* Do not enlarge, and do not exceed maximum of $stdWidths. */}}
187
+ {{- $widths = $widths | append . }}
188
+ {{- end }}
189
+ {{- end }}
190
+ {{- end }}
191
+ {{- else }}
192
+ {{- /* The width was not speficied, will be using $stdWidths. */}}
193
+ {{- $stdWidths = $stdWidths | append $r.Width | sort }}
194
+ {{- range $stdWidths }}
195
+ {{- /* Do not enlarge. */}}
196
+ {{- if (le . $r.Width) }}
197
+ {{- $widths = $widths | append . }}
198
+ {{- end }}
199
+ {{- end }}
200
+ {{- end }}
201
+ {{- $widths = $widths | uniq | sort}}
202
+
203
+ {{- /* Create fallback image (fi) with the smallest of widths. */}}
204
+ {{- $fi := $r.Resize (printf "%dx %s" (math.Min $widths | int) $fallbackFormat) }}
205
+
206
+ {{- /* Create the image map. */}}
207
+ {{- $im := dict }}
208
+ {{- range $format := $formats }}
209
+ {{- $sizes := slice }}
210
+ {{- range sort $widths }}
211
+ {{- $sizes = $sizes | append ($r.Resize (printf "%dx %s" . $format)) }}
212
+ {{- end }}
213
+ {{- $im = merge $im (dict $format $sizes) }}
214
+ {{- end }}
215
+
216
+ {{- /* Render. */}}
217
+ <picture>
218
+ {{- range $formats }}
219
+ {{- with index $im . }}
220
+ {{- $sizes := $stdSizes }}
221
+ {{- with $width }}
222
+ {{- $sizes = printf "%dpx" . }}
223
+ {{- end }}
224
+ <source type="{{ (index . 0).MediaType.Type }}" data-srcset="
225
+ {{- range $k, $_ := . }}
226
+ {{- if $k }},{{- end }}
227
+ {{- printf `%s %dw` .RelPermalink .Width }}
228
+ {{- end }}"
229
+ data-sizes="{{ $stdSizes }}">
230
+ {{- end }}
231
+ {{- end }}
232
+ <img
233
+ src="data:{{ $l.MediaType }};base64,{{ $l.Content | base64Encode }}"
234
+ data-src="{{ $fi.RelPermalink }}"
235
+ width="{{ string $r.Width }}"
236
+ height="{{ string $r.Height }}"
237
+ decoding="{{ $decoding }}"
238
+ fetchpriority="{{ $fetchPriority }}"
239
+ loading="{{ $loading }}"
240
+ alt="{{ $alt }}"
241
+ {{- with .title }}title="{{ $title }}"{{- end }}
242
+ class="lazyload blur-up{{- with .class }} {{ . }}{{- end }}"
243
+ >
244
+ </picture>
245
+
246
+ {{- define "partials/inline/capture-resource.html" }}
247
+ {{- /* Parse destination. */}}
248
+ {{- $u := urls.Parse .path }}
249
+
250
+ {{- /* Set common message. */}}
251
+ {{- $msg := printf "The %q partial was unable to get %q in %s" .partialName $u.String .contentPath }}
252
+
253
+ {{- /* Get image resource. */}}
254
+ {{- $r := "" }}
255
+ {{- if $u.IsAbs }}
256
+ {{- with resources.GetRemote $u.String }}
257
+ {{- with .Err }}
258
+ {{- errorf "%s. See %s" . $.contentPath }}
259
+ {{- else }}
260
+ {{- /* Destination is a remote resource. */}}
261
+ {{- $r = . }}
262
+ {{- end }}
263
+ {{- else }}
264
+ {{- errorf $msg }}
265
+ {{- end }}
266
+ {{- else }}
267
+ {{- with .page.Resources.Get (strings.TrimPrefix "./" $u.Path) }}
268
+ {{- /* Destination is a page resource. */}}
269
+ {{- $r = . }}
270
+ {{- else }}
271
+ {{- with (and (ne .page.BundleType "leaf") (.page.CurrentSection.Resources.Get (strings.TrimPrefix "./" $u.Path)) ) }}
272
+ {{- /* Destination is a section resource, and current page is not a leaf bundle. */}}
273
+ {{- $r = . }}
274
+ {{- else }}
275
+ {{- with resources.Get $u.Path }}
276
+ {{- /* Destination is a global resource. */}}
277
+ {{- $r = . }}
278
+ {{- else }}
279
+ {{- errorf $msg }}
280
+ {{- end }}
281
+ {{- end }}
282
+ {{- end }}
283
+ {{- end }}
284
+ {{- return $r }}
285
+ {{- end -}}
@@ -0,0 +1,137 @@
1
+ {{- /* Last modified: 2023-09-04T20:30:30-07:00 */}}
2
+
3
+ {{- /*
4
+ Copyright 2023 Veriphor LLC
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ use this file except in compliance with the License. You may obtain a copy of
8
+ the License at
9
+
10
+ https://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ License for the specific language governing permissions and limitations under
16
+ the License.
17
+ */}}
18
+
19
+ {{- /*
20
+ Renders an HTML figure element, in multiple formats and sizes.
21
+
22
+ It resolves internal destinations by looking for a matching:
23
+
24
+ 1. Page resource (an image in the current page bundle)
25
+ 2. Section resource (an image in the current section)
26
+ 3. Global resource (an image in the assets directory)
27
+
28
+ It skips the section resource lookup if the current page is a leaf bundle, and
29
+ captures external destinations as resources for local hosting. The build will
30
+ fail if this shortcode is unable to resolve a destination.
31
+
32
+ You must place global resources in the assets directory. If you have placed
33
+ your resources in the static directory, and you are unable or unwilling to move
34
+ them, you must mount the static directory to the assets directory by including
35
+ both of these entries in your site configuration:
36
+
37
+ [[module.mounts]]
38
+ source = 'assets'
39
+ target = 'assets'
40
+
41
+ [[module.mounts]]
42
+ source = 'static'
43
+ target = 'assets'
44
+
45
+ Add this CSS to your site to enable responsive image behavior:
46
+
47
+ img {
48
+ height: auto;
49
+ max-width: 100%;
50
+ }
51
+
52
+ Add this CSS to your site to remove small gaps between adjacent elements:
53
+
54
+ img, picture {
55
+ font-size: 0;
56
+ }
57
+
58
+ This shortcode is a wrapper for, and requires, the figure partial:
59
+ <https://www.veriphor.com/articles/images-with-overlays/#partial-source-code>
60
+
61
+ @context {string} Inner The content between the opening and closing shortcode tags.
62
+ @context {string} InnerDeindent The content between the opening and closing shortcode tags with indentation removed.
63
+ @context {string} Name The file name of the shortcode template, excluding the extension.
64
+ @context {int} Ordinal The zero-based ordinal of the shortcode on the page, or within its parent shortcode.
65
+ @context {page} Page A reference to the page containing the shortcode.
66
+ @context {map} Params The parameters specified in the opening shortcode tag.
67
+ @context {hugolib.ShortcodeWithPage} Parent The context of the parent shortcode.
68
+ @context {text.Position} Position The position of the shortcode within the page content.
69
+
70
+ @method {any} Get Returns the parameter value for the given key (for named parameters) or position (for positional parameters).
71
+ @mathod {bool} IsNamedParams Returns true if the shortcode is called with named instead of positional parameters.
72
+ @method {maps.Scratch) Scratch Returns a writable Scratch to store and manipulate data.
73
+
74
+ @param {string} [src] The path to the image: a page resource, a global resource, or a remote resource.
75
+ @param {int} [width] The display width of the image, in pixels, falling back to 100% of the viewport width.
76
+ @param {string} [sizes] = "" # "100vw", "75vw", or "auto" for example
77
+ @param {string slice} [formats] A slice of image formats, ordered by precedence, to use when creating images for the srcset attribute of each source element.
78
+ @param {string} [process] = "" # "fill 1600x900" for example
79
+ @param {string} [lqip] = "" # "16x webp q20" or "21x webp q20" for example
80
+ @param {string} [decoding] The img element's decoding attribute.
81
+ @param {string} [fetchpriority] The img element's fetchpriority attribute.
82
+ @param {string} [loading] The img element's loading attribute.
83
+ @param {string} [alt] The img element's alt attribute.
84
+ @param {string} [title] The img element's title attribute.
85
+ @param {string} [caption] The figure caption element.
86
+ @param {string} [class] The img element's class attribute.
87
+
88
+ @returns {template.HTML}
89
+
90
+ @example (required args only)
91
+
92
+ {{< figure src="images/zion-national-park.jpg" >}}
93
+
94
+ @example (all args)
95
+
96
+ {{< figure
97
+ src="images/bryce-canyon-national-park.jpg"
98
+ width=768
99
+ sizes="75w"
100
+ formats="webp, jpeg"
101
+ process="fill 1600x900"
102
+ lqip="16x webp q20"
103
+ decoding="async"
104
+ fetchpriority="auto"
105
+ loading="eager"
106
+ alt="Bryce Canyon National Park"
107
+ title="A beautiful day in Bryce Canyon National Park"
108
+ caption="Bryce Canyon National Park"
109
+ class="foo"
110
+ >}}
111
+
112
+ */}}
113
+
114
+ {{- /* Create slices from comma or space separated values. */}}
115
+ {{- $formats := slice }}
116
+ {{- with .Get "formats" }}
117
+ {{- range partial "inline/split.html" . }}
118
+ {{- $formats = $formats | append . }}
119
+ {{- end }}
120
+ {{- end }}
121
+
122
+ {{- /* Build the context to send to the figure partial. */}}
123
+ {{- $ctx := merge .Params
124
+ (dict "page" .Page)
125
+ (dict "formats" $formats)
126
+ }}
127
+
128
+ {{- /* Call the figure partial. */}}
129
+ {{- partial "figure.html" $ctx -}}
130
+
131
+ {{- /* Returns a slice of strings, splitting s by a comma or whitespace. */}}
132
+ {{- define "partials/inline/split.html" }}
133
+ {{- $s := trim . " " }}
134
+ {{- $s = replace $s " " "," }}
135
+ {{- $s := replaceRE `,{2,}` "," $s }}
136
+ {{- return split $s "," }}
137
+ {{- end -}}