@@ -5,8 +5,6 @@ import MagicString from 'magic-string';
5
5
import { asyncWalk } from 'estree-walker' ;
6
6
import { parse } from 'svelte-parse-markup' ;
7
7
8
- const ASSET_PREFIX = '___ASSET___' ;
9
-
10
8
// TODO: expose this in vite-imagetools rather than duplicating it
11
9
const OPTIMIZABLE = / ^ [ ^ ? ] + \. ( a v i f | h e i f | g i f | j p e g | j p g | p n g | t i f f | w e b p ) ( \? .* ) ? $ / ;
12
10
@@ -35,11 +33,20 @@ export function image(opts) {
35
33
const s = new MagicString ( content ) ;
36
34
const ast = parse ( content , { filename } ) ;
37
35
38
- // Import path to import name
39
- // e.g. ./foo.png => ___ASSET___0
40
- /** @type {Map<string, string> } */
36
+ /**
37
+ * Import path to import name
38
+ * e.g. ./foo.png => __IMPORTED_ASSET_0__
39
+ * @type {Map<string, string> }
40
+ */
41
41
const imports = new Map ( ) ;
42
42
43
+ /**
44
+ * Vite name to declaration name
45
+ * e.g. __VITE_ASSET_0__ => __DECLARED_ASSET_0__
46
+ * @type {Map<string, string> }
47
+ */
48
+ const consts = new Map ( ) ;
49
+
43
50
/**
44
51
* @param {import('svelte/types/compiler/interfaces').TemplateNode } node
45
52
* @param {{ type: string, start: number, end: number, raw: string } } src_attribute
@@ -94,10 +101,10 @@ export function image(opts) {
94
101
image = await process ( resolved_id , opts ) ;
95
102
images . set ( resolved_id , image ) ;
96
103
}
97
- s . update ( node . start , node . end , img_to_picture ( content , node , image ) ) ;
104
+ s . update ( node . start , node . end , img_to_picture ( consts , content , node , image ) ) ;
98
105
} else {
99
- // e.g. <img src="./foo.svg" /> => <img src={___ASSET___0 } />
100
- const name = ASSET_PREFIX + imports . size ;
106
+ // e.g. <img src="./foo.svg" /> => <img src={__IMPORTED_ASSET_0__ } />
107
+ const name = '__IMPORTED_ASSET_' + imports . size + '__' ;
101
108
const { start, end } = src_attribute ;
102
109
// update src with reference to imported asset
103
110
s . update (
@@ -131,18 +138,31 @@ export function image(opts) {
131
138
132
139
// add imports
133
140
if ( imports . size ) {
134
- let import_text = '' ;
141
+ let text = '' ;
135
142
for ( const [ path , import_name ] of imports . entries ( ) ) {
136
- import_text += `import ${ import_name } from "${ path } ";` ;
143
+ text += `import ${ import_name } from "${ path } ";` ;
137
144
}
138
145
if ( ast . instance ) {
139
146
// @ts -ignore
140
- s . appendLeft ( ast . instance . content . start , import_text ) ;
147
+ s . appendLeft ( ast . instance . content . start , text ) ;
141
148
} else {
142
- s . append ( `<script>${ import_text } </script>` ) ;
149
+ s . prepend ( `<script>${ text } </script>` ) ;
143
150
}
144
151
}
145
152
153
+ if ( consts . size ) {
154
+ let text = ''
155
+ for ( const [ vite_name , declaration_name ] of consts . entries ( ) ) {
156
+ text += `\tconst ${ declaration_name } = "${ vite_name } ";\n`
157
+ }
158
+ if ( ast . module ) {
159
+ // @ts -ignore
160
+ s . appendLeft ( ast . module . content . start , text )
161
+ } else {
162
+ s . prepend ( `<script context="module">\n${ text } </script>\n` )
163
+ }
164
+ }
165
+
146
166
return {
147
167
code : s . toString ( ) ,
148
168
map : s . generateMap ( )
@@ -264,11 +284,12 @@ function stringToNumber(param) {
264
284
}
265
285
266
286
/**
287
+ * @param {Map<string,string> } consts
267
288
* @param {string } content
268
289
* @param {import('svelte/types/compiler/interfaces').TemplateNode } node
269
290
* @param {import('vite-imagetools').Picture } image
270
291
*/
271
- function img_to_picture ( content , node , image ) {
292
+ function img_to_picture ( consts , content , node , image ) {
272
293
/** @type {Array<import('svelte/types/compiler/interfaces').BaseDirective | import('svelte/types/compiler/interfaces').Attribute | import('svelte/types/compiler/interfaces').SpreadAttribute> } attributes */
273
294
const attributes = node . attributes ;
274
295
const index = attributes . findIndex ( ( attribute ) => attribute . name === 'sizes' ) ;
@@ -281,11 +302,11 @@ function img_to_picture(content, node, image) {
281
302
let res = '<picture>' ;
282
303
283
304
for ( const [ format , srcset ] of Object . entries ( image . sources ) ) {
284
- res += `<source srcset=${ to_value ( srcset ) } ${ sizes_string } type="image/${ format } " />` ;
305
+ res += `<source srcset=${ to_value ( consts , srcset ) } ${ sizes_string } type="image/${ format } " />` ;
285
306
}
286
307
287
308
res += `<img ${ serialize_img_attributes ( content , attributes , {
288
- src : to_value ( image . img . src ) ,
309
+ src : to_value ( consts , image . img . src ) ,
289
310
width : image . img . w ,
290
311
height : image . img . h
291
312
} ) } />`;
@@ -294,10 +315,19 @@ function img_to_picture(content, node, image) {
294
315
}
295
316
296
317
/**
318
+ * @param {Map<string, string> } consts
297
319
* @param {string } src
298
320
*/
299
- function to_value ( src ) {
300
- return src . startsWith ( '__VITE_ASSET__' ) ? `{"${ src } "}` : `"${ src } "` ;
321
+ function to_value ( consts , src ) {
322
+ if ( src . startsWith ( '__VITE_ASSET__' ) ) {
323
+ let var_name = consts . get ( src ) ;
324
+ if ( ! var_name ) {
325
+ var_name = '__DECLARED_ASSET_' + consts . size + '__' ;
326
+ consts . set ( src , var_name ) ;
327
+ }
328
+ return `{"${ var_name } "}` ;
329
+ }
330
+ return `"${ src } "` ;
301
331
}
302
332
303
333
/**
0 commit comments