@@ -280,7 +280,7 @@ describe('getImage', () => {
280280 assert . equal ( result . attributes . position , undefined ) ;
281281 } ) ;
282282
283- it ( 'includes object-position in style attribute when position is provided ' , async ( ) => {
283+ it ( 'does not add inline style for position (CSP compliance) ' , async ( ) => {
284284 const result = await renderImage ( {
285285 src : 'https://example.com/photo.jpg' ,
286286 width : 300 ,
@@ -290,10 +290,24 @@ describe('getImage', () => {
290290 position : 'left top' ,
291291 } ) ;
292292
293- assert . match ( result . attributes . style , / o b j e c t - p o s i t i o n : \s * l e f t t o p / ) ;
293+ // Position should only live in the data attribute, not in inline styles
294+ assert . equal ( result . attributes [ 'data-astro-image-pos' ] , 'left-top' ) ;
295+ const style = result . attributes . style ;
296+ if ( typeof style === 'string' ) {
297+ assert . ok (
298+ ! style . includes ( 'object-position' ) ,
299+ 'inline style should not contain object-position' ,
300+ ) ;
301+ } else if ( typeof style === 'object' && style !== null ) {
302+ assert . equal (
303+ 'objectPosition' in style ,
304+ false ,
305+ 'style object should not contain objectPosition' ,
306+ ) ;
307+ }
294308 } ) ;
295309
296- it ( 'merges position into existing style object without overwriting ' , async ( ) => {
310+ it ( 'preserves user-provided style without injecting position ' , async ( ) => {
297311 const result = await renderImage ( {
298312 src : 'https://example.com/photo.jpg' ,
299313 width : 300 ,
@@ -304,15 +318,14 @@ describe('getImage', () => {
304318 style : { color : 'red' } ,
305319 } ) ;
306320
307- assert . deepStrictEqual ( result . attributes . style , {
308- color : 'red' ,
309- objectPosition : 'top right' ,
310- } ) ;
321+ // User style should be preserved as-is, position only in data attribute
322+ assert . equal ( result . attributes [ 'data-astro-image-pos' ] , 'top-right' ) ;
323+ assert . deepStrictEqual ( result . attributes . style , { color : 'red' } ) ;
311324 } ) ;
312325 } ) ;
313326
314327 describe ( 'format' , ( ) => {
315- it ( 'defaults to webp format ' , async ( ) => {
328+ it ( 'defaults to webp for remote images with a non-svg extension ' , async ( ) => {
316329 const result = await renderImage ( {
317330 src : 'https://example.com/photo.jpg' ,
318331 width : 800 ,
@@ -324,6 +337,41 @@ describe('getImage', () => {
324337 assert . equal ( params . get ( 'f' ) , 'webp' ) ;
325338 } ) ;
326339
340+ it ( 'defaults to svg for remote URLs ending in .svg so they pass through' , async ( ) => {
341+ const result = await renderImage ( {
342+ src : 'https://example.com/icon.svg' ,
343+ width : 64 ,
344+ height : 64 ,
345+ alt : 'Format test' ,
346+ } ) ;
347+ const params = new URL ( result . src , 'http://localhost' ) . searchParams ;
348+ assert . equal ( params . get ( 'f' ) , 'svg' ) ;
349+ } ) ;
350+
351+ it ( 'defaults to svg for data:image/svg+xml so they pass through' , async ( ) => {
352+ // Data URIs aren't in the test allowlist, so the URL is returned as-is by getURL — verify
353+ // the resolved transform options instead.
354+ const svg = 'data:image/svg+xml,%3Csvg/%3E' ;
355+ const result = await renderImage ( {
356+ src : svg ,
357+ width : 32 ,
358+ height : 32 ,
359+ alt : 'Format test' ,
360+ } ) ;
361+ assert . equal ( result . options . format , 'svg' ) ;
362+ } ) ;
363+
364+ it ( 'omits format param for remote URLs without a detectable extension (resolved by /_image at request time)' , async ( ) => {
365+ const result = await renderImage ( {
366+ src : 'https://example.com/api/avatar' ,
367+ width : 64 ,
368+ height : 64 ,
369+ alt : 'Format test' ,
370+ } ) ;
371+ const params = new URL ( result . src , 'http://localhost' ) . searchParams ;
372+ assert . equal ( params . has ( 'f' ) , false ) ;
373+ } ) ;
374+
327375 it ( 'respects explicit format' , async ( ) => {
328376 const result = await renderImage ( {
329377 src : 'https://example.com/photo.jpg' ,
0 commit comments