@@ -2,7 +2,7 @@ import { extname } from 'node:path';
22import MagicString from 'magic-string' ;
33import type * as vite from 'vite' ;
44import { normalizePath } from 'vite' ;
5- import type { AstroPluginOptions , ImageTransform } from '../@types/astro.js' ;
5+ import type { AstroPluginOptions , AstroSettings , ImageTransform } from '../@types/astro.js' ;
66import { extendManualChunks } from '../core/build/plugins/util.js' ;
77import { AstroError , AstroErrorData } from '../core/errors/index.js' ;
88import {
@@ -24,6 +24,71 @@ const resolvedVirtualModuleId = '\0' + VIRTUAL_MODULE_ID;
2424
2525const assetRegex = new RegExp ( `\\.(${ VALID_INPUT_FORMATS . join ( '|' ) } )` , 'i' ) ;
2626const assetRegexEnds = new RegExp ( `\\.(${ VALID_INPUT_FORMATS . join ( '|' ) } )$` , 'i' ) ;
27+ const addStaticImageFactory = (
28+ settings : AstroSettings
29+ ) : typeof globalThis . astroAsset . addStaticImage => {
30+ return ( options , hashProperties , originalFSPath ) => {
31+ if ( ! globalThis . astroAsset . staticImages ) {
32+ globalThis . astroAsset . staticImages = new Map <
33+ string ,
34+ {
35+ originalSrcPath : string ;
36+ transforms : Map < string , { finalPath : string ; transform : ImageTransform } > ;
37+ }
38+ > ( ) ;
39+ }
40+
41+ // Rollup will copy the file to the output directory, as such this is the path in the output directory, including the asset prefix / base
42+ const ESMImportedImageSrc = isESMImportedImage ( options . src ) ? options . src . src : options . src ;
43+ const fileExtension = extname ( ESMImportedImageSrc ) ;
44+ const assetPrefix = getAssetsPrefix ( fileExtension , settings . config . build . assetsPrefix ) ;
45+
46+ // This is the path to the original image, from the dist root, without the base or the asset prefix (e.g. /_astro/image.hash.png)
47+ const finalOriginalPath = removeBase (
48+ removeBase ( ESMImportedImageSrc , settings . config . base ) ,
49+ assetPrefix
50+ ) ;
51+
52+ const hash = hashTransform ( options , settings . config . image . service . entrypoint , hashProperties ) ;
53+
54+ let finalFilePath : string ;
55+ let transformsForPath = globalThis . astroAsset . staticImages . get ( finalOriginalPath ) ;
56+ let transformForHash = transformsForPath ?. transforms . get ( hash ) ;
57+
58+ // If the same image has already been transformed with the same options, we'll reuse the final path
59+ if ( transformsForPath && transformForHash ) {
60+ finalFilePath = transformForHash . finalPath ;
61+ } else {
62+ finalFilePath = prependForwardSlash (
63+ joinPaths (
64+ isESMImportedImage ( options . src ) ? '' : settings . config . build . assets ,
65+ prependForwardSlash ( propsToFilename ( finalOriginalPath , options , hash ) )
66+ )
67+ ) ;
68+
69+ if ( ! transformsForPath ) {
70+ globalThis . astroAsset . staticImages . set ( finalOriginalPath , {
71+ originalSrcPath : originalFSPath ,
72+ transforms : new Map ( ) ,
73+ } ) ;
74+ transformsForPath = globalThis . astroAsset . staticImages . get ( finalOriginalPath ) ! ;
75+ }
76+
77+ transformsForPath . transforms . set ( hash , {
78+ finalPath : finalFilePath ,
79+ transform : options ,
80+ } ) ;
81+ }
82+
83+ // The paths here are used for URLs, so we need to make sure they have the proper format for an URL
84+ // (leading slash, prefixed with the base / assets prefix, encoded, etc)
85+ if ( settings . config . build . assetsPrefix ) {
86+ return encodeURI ( joinPaths ( assetPrefix , finalFilePath ) ) ;
87+ } else {
88+ return encodeURI ( prependForwardSlash ( joinPaths ( settings . config . base , finalFilePath ) ) ) ;
89+ }
90+ } ;
91+ } ;
2792
2893export default function assets ( {
2994 settings,
@@ -92,73 +157,7 @@ export default function assets({
92157 return ;
93158 }
94159
95- globalThis . astroAsset . addStaticImage = ( options , hashProperties , originalFSPath ) => {
96- if ( ! globalThis . astroAsset . staticImages ) {
97- globalThis . astroAsset . staticImages = new Map <
98- string ,
99- {
100- originalSrcPath : string ;
101- transforms : Map < string , { finalPath : string ; transform : ImageTransform } > ;
102- }
103- > ( ) ;
104- }
105-
106- // Rollup will copy the file to the output directory, as such this is the path in the output directory, including the asset prefix / base
107- const ESMImportedImageSrc = isESMImportedImage ( options . src )
108- ? options . src . src
109- : options . src ;
110- const fileExtension = extname ( ESMImportedImageSrc ) ;
111- const assetPrefix = getAssetsPrefix ( fileExtension , settings . config . build . assetsPrefix ) ;
112-
113- // This is the path to the original image, from the dist root, without the base or the asset prefix (e.g. /_astro/image.hash.png)
114- const finalOriginalPath = removeBase (
115- removeBase ( ESMImportedImageSrc , settings . config . base ) ,
116- assetPrefix
117- ) ;
118-
119- const hash = hashTransform (
120- options ,
121- settings . config . image . service . entrypoint ,
122- hashProperties
123- ) ;
124-
125- let finalFilePath : string ;
126- let transformsForPath = globalThis . astroAsset . staticImages . get ( finalOriginalPath ) ;
127- let transformForHash = transformsForPath ?. transforms . get ( hash ) ;
128-
129- // If the same image has already been transformed with the same options, we'll reuse the final path
130- if ( transformsForPath && transformForHash ) {
131- finalFilePath = transformForHash . finalPath ;
132- } else {
133- finalFilePath = prependForwardSlash (
134- joinPaths (
135- isESMImportedImage ( options . src ) ? '' : settings . config . build . assets ,
136- prependForwardSlash ( propsToFilename ( finalOriginalPath , options , hash ) )
137- )
138- ) ;
139-
140- if ( ! transformsForPath ) {
141- globalThis . astroAsset . staticImages . set ( finalOriginalPath , {
142- originalSrcPath : originalFSPath ,
143- transforms : new Map ( ) ,
144- } ) ;
145- transformsForPath = globalThis . astroAsset . staticImages . get ( finalOriginalPath ) ! ;
146- }
147-
148- transformsForPath . transforms . set ( hash , {
149- finalPath : finalFilePath ,
150- transform : options ,
151- } ) ;
152- }
153-
154- // The paths here are used for URLs, so we need to make sure they have the proper format for an URL
155- // (leading slash, prefixed with the base / assets prefix, encoded, etc)
156- if ( settings . config . build . assetsPrefix ) {
157- return encodeURI ( joinPaths ( assetPrefix , finalFilePath ) ) ;
158- } else {
159- return encodeURI ( prependForwardSlash ( joinPaths ( settings . config . base , finalFilePath ) ) ) ;
160- }
161- } ;
160+ globalThis . astroAsset . addStaticImage = addStaticImageFactory ( settings ) ;
162161 } ,
163162 // In build, rewrite paths to ESM imported images in code to their final location
164163 async renderChunk ( code ) {
0 commit comments