@@ -3,34 +3,42 @@ import { imagetools } from 'vite-imagetools';
33import { image_plugin } from './vite-plugin.js' ;
44
55/**
6+ * @param {import('types/index.js').VitePluginOptions } [opts]
67 * @returns {import('vite').Plugin[] }
78 */
8- export function enhancedImages ( ) {
9- const imagetools_instance = imagetools_plugin ( ) ;
9+ export function enhancedImages ( opts ) {
10+ const imagetools_instance = imagetools_plugin ( opts ) ;
1011 return ! process . versions . webcontainer
1112 ? [ image_plugin ( imagetools_instance ) , imagetools_instance ]
1213 : [ ] ;
1314}
1415
1516/**
16- * @param {import('sharp ').Metadata } meta
17- * @returns {string }
17+ * @param {import('types/index.js ').VitePluginOptions } [opts]
18+ * @returns {import('vite').Plugin }
1819 */
19- function fallback_format ( meta ) {
20- if ( meta . pages && meta . pages > 1 ) {
21- return meta . format === 'tiff' ? 'tiff' : 'gif' ;
22- }
23- if ( meta . hasAlpha ) {
24- return 'png' ;
25- }
26- return 'jpg' ;
27- }
20+ function imagetools_plugin ( opts ) {
21+ const get_formats = opts ?. defaultFormats ?? default_formats ;
22+ const get_widths = opts ?. defaultWidths ?? default_widths ;
2823
29- function imagetools_plugin ( ) {
3024 /** @type {Partial<import('vite-imagetools').VitePluginOptions> } */
3125 const imagetools_opts = {
32- defaultDirectives : async ( { pathname, searchParams : qs } , metadata ) => {
33- if ( ! qs . has ( 'enhanced' ) ) return new URLSearchParams ( ) ;
26+ ...opts ?. imagetools ,
27+
28+ defaultDirectives : async ( url , metadata ) => {
29+ const { pathname, searchParams : qs } = url ;
30+
31+ if ( ! qs . has ( 'enhanced' ) ) {
32+ if ( typeof opts ?. imagetools ?. defaultDirectives === 'function' ) {
33+ return opts . imagetools . defaultDirectives ( url , metadata ) ;
34+ }
35+
36+ if ( opts ?. imagetools ?. defaultDirectives ) {
37+ return opts . imagetools . defaultDirectives ;
38+ }
39+
40+ return new URLSearchParams ( ) ;
41+ }
3442
3543 const meta = await metadata ( ) ;
3644
@@ -42,12 +50,10 @@ function imagetools_plugin() {
4250 return new URLSearchParams ( ) ;
4351 }
4452
45- const { widths, kind } = get_widths ( width , qs . get ( 'imgSizes' ) ) ;
4653 return new URLSearchParams ( {
4754 as : 'picture' ,
48- format : `avif;webp;${ fallback_format ( meta ) } ` ,
49- w : widths . join ( ';' ) ,
50- ...( kind === 'x' && ! qs . has ( 'w' ) && { basePixels : widths [ 0 ] . toString ( ) } )
55+ format : get_formats ( meta ) ,
56+ ...get_widths ( width , qs . get ( 'imgSizes' ) )
5157 } ) ;
5258 } ,
5359 namedExports : false
@@ -59,12 +65,28 @@ function imagetools_plugin() {
5965 return imagetools ( imagetools_opts ) ;
6066}
6167
68+ /**
69+ * @param {import('sharp').Metadata } meta
70+ * @returns {string }
71+ */
72+ function default_formats ( meta ) {
73+ let fallback = 'jpg' ;
74+
75+ if ( meta . pages && meta . pages > 1 ) {
76+ fallback = meta . format === 'tiff' ? 'tiff' : 'gif' ;
77+ } else if ( meta . hasAlpha ) {
78+ fallback = 'png' ;
79+ }
80+
81+ return `avif;webp;${ fallback } ` ;
82+ }
83+
6284/**
6385 * @param {number } width
6486 * @param {string | null } sizes
65- * @returns {{ widths: number[]; kind: 'w' | 'x' } }
87+ * @returns {{ w: string; basePixels?: string } }
6688 */
67- function get_widths ( width , sizes ) {
89+ function default_widths ( width , sizes ) {
6890 // We don't really know what the user wants here. But if they have an image that's really big
6991 // then we can probably assume they're always displaying it full viewport/breakpoint.
7092 // If the user is displaying a responsive image then the size usually doesn't change that much
@@ -79,9 +101,7 @@ function get_widths(width, sizes) {
79101 // https://screensiz.es/
80102 // https://gs.statcounter.com/screen-resolution-stats (note: logical. we want physical)
81103 // Include 1080 because lighthouse uses a moto g4 with 360 logical pixels and 3x pixel ratio.
82- const widths = [ 540 , 768 , 1080 , 1366 , 1536 , 1920 , 2560 , 3000 , 4096 , 5120 ] ;
83- widths . push ( width ) ;
84- return { widths, kind : 'w' } ;
104+ return { w : `540;768;1080;1366;1536;1920;2560;3000;4096;5120${ width } ` } ;
85105 }
86106
87107 // Don't need more than 2x resolution. Note that due to this optimization, pixel density
@@ -94,5 +114,6 @@ function get_widths(width, sizes) {
94114 // data. Even true 3x resolution screens are wasteful as the human eye cannot see that level of
95115 // detail without something like a magnifying glass.
96116 // https://blog.twitter.com/engineering/en_us/topics/infrastructure/2019/capping-image-fidelity-on-ultra-high-resolution-devices.html
97- return { widths : [ Math . round ( width / 2 ) , width ] , kind : 'x' } ;
117+ const small_width = Math . round ( width / 2 ) . toString ( ) ;
118+ return { w : `${ small_width } ;${ width } ` , basePixels : small_width } ;
98119}
0 commit comments