11import { optimize } from 'svgo' ;
2- import { parse , renderSync } from 'ultrahtml' ;
2+ import { ELEMENT_NODE , TEXT_NODE , parse , renderSync } from 'ultrahtml' ;
33import { AstroError , AstroErrorData } from '../../core/errors/index.js' ;
44import type { AstroConfig } from '../../types/public/config.js' ;
55import type { SvgComponentProps } from '../runtime.js' ;
@@ -33,15 +33,29 @@ function parseSvg({
3333 }
3434 const root = parse ( processedContents ) ;
3535 const svgNode = root . children . find (
36- ( { name, type } : { name : string ; type : number } ) => type === 1 /* Element */ && name === 'svg' ,
36+ ( { name, type } : { name : string ; type : number } ) => type === ELEMENT_NODE && name === 'svg' ,
3737 ) ;
3838 if ( ! svgNode ) {
3939 throw new Error ( 'SVG file does not contain an <svg> element' ) ;
4040 }
4141 const { attributes, children } = svgNode ;
4242 const body = renderSync ( { ...root , children } ) ;
4343
44- return { attributes, body } ;
44+ // Collect text content of <style> elements for head propagation and CSP hashing
45+ const styles : string [ ] = [ ] ;
46+ for ( const child of children ) {
47+ if ( child . type === ELEMENT_NODE && child . name === 'style' ) {
48+ const textContent = child . children
49+ ?. filter ( ( c : { type : number } ) => c . type === TEXT_NODE )
50+ . map ( ( c : { value : string } ) => c . value )
51+ . join ( '' ) ;
52+ if ( textContent ) {
53+ styles . push ( textContent ) ;
54+ }
55+ }
56+ }
57+
58+ return { attributes, body, styles } ;
4559}
4660
4761export function makeSvgComponent (
@@ -50,7 +64,11 @@ export function makeSvgComponent(
5064 svgoConfig : AstroConfig [ 'experimental' ] [ 'svgo' ] ,
5165) : string {
5266 const file = typeof contents === 'string' ? contents : contents . toString ( 'utf-8' ) ;
53- const { attributes, body : children } = parseSvg ( {
67+ const {
68+ attributes,
69+ body : children ,
70+ styles,
71+ } = parseSvg ( {
5472 path : meta . fsPath ,
5573 contents : file ,
5674 svgoConfig,
@@ -59,6 +77,7 @@ export function makeSvgComponent(
5977 meta,
6078 attributes : dropAttributes ( attributes ) ,
6179 children,
80+ styles,
6281 } ;
6382
6483 return `import { createSvgComponent } from 'astro/assets/runtime';
@@ -74,12 +93,16 @@ export function parseSvgComponentData(
7493 meta : ImageMetadata ,
7594 contents : Buffer | string ,
7695 svgoConfig : AstroConfig [ 'experimental' ] [ 'svgo' ] ,
77- ) : { attributes : Record < string , string > ; children : string } {
96+ ) : { attributes : Record < string , string > ; children : string ; styles : string [ ] } {
7897 const file = typeof contents === 'string' ? contents : contents . toString ( 'utf-8' ) ;
79- const { attributes, body : children } = parseSvg ( {
98+ const {
99+ attributes,
100+ body : children ,
101+ styles,
102+ } = parseSvg ( {
80103 path : meta . fsPath ,
81104 contents : file ,
82105 svgoConfig,
83106 } ) ;
84- return { attributes : dropAttributes ( attributes ) , children } ;
107+ return { attributes : dropAttributes ( attributes ) , children, styles } ;
85108}
0 commit comments