@massimo-cassandro/minimo 1.14.5 → 1.14.6
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.
package/package.json
CHANGED
|
@@ -5,10 +5,13 @@ import { classnames } from './classnames.js';
|
|
|
5
5
|
/**
|
|
6
6
|
* @typedef {Object} PictureSizeEntry
|
|
7
7
|
* @property {number} [from] - Breakpoint (px) the size applies from (`width >=` media condition); omitted in the (single) mobile-first default entry.
|
|
8
|
-
* @property {number | [number, number]} size - Rendered width (px, height computed with `ratio
|
|
8
|
+
* @property {number | [number, number]} size - Rendered width (px, height computed with `ratio`, if set) or explicit `[width, height]` pair (px).
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
// TODO aggiungere compatibilità con immagini Unsplash basate su imgix
|
|
12
|
+
// TODO parametri viewer: le convenzioni attuali (`bb=WxH`, `bb=Wx` per il resize width-only,
|
|
13
|
+
// `q`, `fd`, `f`) sono legate al viewer interno; prevedere un meccanismo di astrazione
|
|
14
|
+
// per altri servizi con parametri diversi (es. imgix/Unsplash)
|
|
12
15
|
|
|
13
16
|
/**
|
|
14
17
|
* Creates a `picture` domBuilder item for an image rendered through the viewer.
|
|
@@ -20,7 +23,9 @@ import { classnames } from './classnames.js';
|
|
|
20
23
|
* `(width >= …)` media condition (range syntax).
|
|
21
24
|
*
|
|
22
25
|
* @example
|
|
23
|
-
* // fixed-width thumb (250px,
|
|
26
|
+
* // fixed-width thumb (250px, 1x and 2x candidates); with no `ratio` nor explicit
|
|
27
|
+
* // heights, the viewer gets a width-only resize (bb=250x) and the `img` has no
|
|
28
|
+
* // `height` attribute
|
|
24
29
|
* buildPictureTag({ baseSrc: 'https://img-viewer.example.com/abc123', alt: '…' });
|
|
25
30
|
* // sizes="250px", srcset="… 250w, … 500w"
|
|
26
31
|
*
|
|
@@ -55,15 +60,24 @@ import { classnames } from './classnames.js';
|
|
|
55
60
|
* // dev environment (no avif) and above-the-fold img (no loading="lazy")
|
|
56
61
|
* buildPictureTag({ baseSrc, devMode: true, lazy: false });
|
|
57
62
|
*
|
|
63
|
+
* @example
|
|
64
|
+
* // onLoad callback: reveal the image once it has finished loading
|
|
65
|
+
* buildPictureTag({
|
|
66
|
+
* baseSrc,
|
|
67
|
+
* imgExtraClass: 'img-loading',
|
|
68
|
+
* onLoad: img => img.classList.remove('img-loading'),
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
58
71
|
* @param {Object} args
|
|
59
72
|
* @param {string} args.baseSrc - Image base URL (viewer endpoint); its query params are preserved.
|
|
60
73
|
* @param {(number | [number, number] | PictureSizeEntry)[]} [args.sizes=[250]] - Rendered image sizes, in any order. Each entry is a `{from, size}` object (see {@link PictureSizeEntry}); a bare number or `[width, height]` pair is a shorthand for the mobile-first default entry (the one without `from`), expected exactly once.
|
|
61
|
-
* @param {number} [args.ratio=
|
|
74
|
+
* @param {number|null} [args.ratio=null] - Default aspect ratio (width / height, as in the CSS `aspect-ratio` property) used to compute the height of numeric sizes. When null, no height is computed: the height-related output (`height` attribute, height in the `bb` param) is omitted and the viewer preserves the image's own ratio.
|
|
62
75
|
* @param {number} [args.dpr=2] - Maximum pixel density (integer): `srcset` candidates are generated for every density from 1 to `dpr`.
|
|
63
|
-
* @param {[string, string|number][]} [args.img_params=[['q','60']
|
|
76
|
+
* @param {[string, string|number][]} [args.img_params=[['q','60']]] - Query params (`[name, value]` pairs) added to every generated URL.
|
|
64
77
|
* @param {string[]} [args.formats=['avif','webp','pjpg']] - Image formats: the last one is used for the `img` fallback element, the others for the `source` elements.
|
|
65
78
|
* @param {boolean} [args.devMode=false] - When true, `avif` is excluded from `formats` (not supported by the local dev environment).
|
|
66
79
|
* @param {boolean} [args.lazy=true] - When true, the `img` element gets `loading="lazy"`.
|
|
80
|
+
* @param {'high'|'low'|null} [args.fetchpriority=null] - `fetchpriority` attribute for the `img` element: use `high` for the LCP/above-the-fold image (typically with `lazy: false`). When null the attribute is omitted (browser default `auto`).
|
|
67
81
|
* @param {((img: HTMLImageElement) => void) | null} [args.onLoad=null] - Called once the image has finished loading, receiving the `img` element (called immediately if the image is already complete).
|
|
68
82
|
* @param {boolean} [args.condition=true] - When false, the function returns `null` without building anything.
|
|
69
83
|
* @param {boolean} [args.legacyMediaSyntax=false] - When true, the `sizes` media conditions use `(min-width: …)` instead of the range syntax `(width >= …)`, for older browsers (pre Chrome/Edge 104, Firefox 102, Safari 16.4).
|
|
@@ -77,12 +91,13 @@ import { classnames } from './classnames.js';
|
|
|
77
91
|
export function buildPictureTag({
|
|
78
92
|
baseSrc,
|
|
79
93
|
sizes = [250],
|
|
80
|
-
ratio =
|
|
94
|
+
ratio = null,
|
|
81
95
|
dpr = 2,
|
|
82
96
|
img_params = [ ['q', '60'] ],
|
|
83
97
|
formats = ['avif', 'webp', 'pjpg'],
|
|
84
98
|
devMode = false,
|
|
85
99
|
lazy = true,
|
|
100
|
+
fetchpriority = null,
|
|
86
101
|
onLoad = null,
|
|
87
102
|
condition = true,
|
|
88
103
|
legacyMediaSyntax = false,
|
|
@@ -109,14 +124,14 @@ export function buildPictureTag({
|
|
|
109
124
|
const dprList = Array.from({length: dpr}, (_, i) => i + 1);
|
|
110
125
|
|
|
111
126
|
// entry di `sizes` normalizzate in oggetti {from, width, height}
|
|
112
|
-
// (per le size numeriche l'altezza è calcolata con `ratio
|
|
127
|
+
// (per le size numeriche l'altezza è calcolata con `ratio`, se presente, altrimenti è null),
|
|
113
128
|
// ordinate per breakpoint, con il default (from = null) per primo
|
|
114
129
|
const sizeEntries = sizes.map(entry => {
|
|
115
130
|
if(typeof entry === 'object' && !Array.isArray(entry)) {
|
|
116
|
-
const [width, height] = Array.isArray(entry.size)? entry.size : [entry.size, Math.floor(entry.size / ratio)];
|
|
131
|
+
const [width, height] = Array.isArray(entry.size)? entry.size : [entry.size, ratio == null? null : Math.floor(entry.size / ratio)];
|
|
117
132
|
return { from: entry.from ?? null, width, height };
|
|
118
133
|
}
|
|
119
|
-
const [width, height] = Array.isArray(entry)? entry : [entry, Math.floor(entry / ratio)];
|
|
134
|
+
const [width, height] = Array.isArray(entry)? entry : [entry, ratio == null? null : Math.floor(entry / ratio)];
|
|
120
135
|
return { from: null, width, height };
|
|
121
136
|
}).sort((a, b) => (a.from ?? 0) - (b.from ?? 0));
|
|
122
137
|
|
|
@@ -135,7 +150,7 @@ export function buildPictureTag({
|
|
|
135
150
|
// dimensioni dei candidati srcset (una per ogni densità da 1 a `dpr`),
|
|
136
151
|
// senza duplicati (per larghezza), in ordine crescente
|
|
137
152
|
,srcsetSizes = sizeEntries
|
|
138
|
-
.flatMap(({width, height}) => dprList.map(d => /** @type {[number, number]} */ ([width * d, height * d])))
|
|
153
|
+
.flatMap(({width, height}) => dprList.map(d => /** @type {[number, number|null]} */ ([width * d, height == null? null : height * d])))
|
|
139
154
|
.filter((pair, idx, arr) => arr.findIndex(p => p[0] === pair[0]) === idx)
|
|
140
155
|
.sort((a, b) => a[0] - b[0])
|
|
141
156
|
|
|
@@ -186,7 +201,8 @@ export function buildPictureTag({
|
|
|
186
201
|
searchParams.set('f', fmt);
|
|
187
202
|
|
|
188
203
|
srcsetSizes.forEach(([w, h]) => {
|
|
189
|
-
|
|
204
|
+
// TODO senza altezza `bb=<w>x` vale per questo viewer: prevedere altre convenzioni (es. imgix)
|
|
205
|
+
searchParams.set('bb', `${w}x${h ?? ''}`);
|
|
190
206
|
base_url.search = searchParams.toString();
|
|
191
207
|
srcsetArray.push(`${base_url.toString()} ${w}w`);
|
|
192
208
|
});
|
|
@@ -204,6 +220,8 @@ export function buildPictureTag({
|
|
|
204
220
|
width: imgWidth,
|
|
205
221
|
height: imgHeight,
|
|
206
222
|
loading: lazy? 'lazy' : null,
|
|
223
|
+
decoding: 'async',
|
|
224
|
+
fetchpriority: fetchpriority,
|
|
207
225
|
...imgExtraAttrs
|
|
208
226
|
},
|
|
209
227
|
callback: onLoad == null? undefined : el => {
|