@@ -19,7 +19,9 @@ const MARKER_PIXEL_RATIO = 2;
1919// enormous canvas; the rendered size is set via the marker image's own pixels.
2020const MIN_MARKER_SIZE = 6 ;
2121const MAX_MARKER_SIZE = 96 ;
22+ const MAX_SVG_SOURCE_CACHE = 64 ;
2223export const KML_ICON_URL_PROPERTY = "__geolibre_kml_icon_url" ;
24+ const svgSourceCache = new Map < string , Promise < string | null > > ( ) ;
2325
2426const BUILTIN_SHAPES : ReadonlySet < MarkerShape > = new Set ( [
2527 "circle" ,
@@ -101,10 +103,21 @@ function replaceSvgColorParameters(markup: string, color: string): string {
101103async function colorizedSvgSource ( markup : string , color : string ) : Promise < string | null > {
102104 let sourceMarkup = markup ;
103105 if ( / ^ (?: h t t p s ? : | d a t a : i m a g e \/ s v g \+ x m l ) / i. test ( markup ) ) {
104- try {
105- const response = await fetch ( markup ) ;
106- if ( response . ok ) sourceMarkup = await response . text ( ) ;
107- } catch {
106+ let pending = svgSourceCache . get ( markup ) ;
107+ if ( ! pending ) {
108+ pending = fetch ( markup )
109+ . then ( ( response ) => ( response . ok ? response . text ( ) : null ) )
110+ . catch ( ( ) => null ) ;
111+ if ( svgSourceCache . size >= MAX_SVG_SOURCE_CACHE ) {
112+ const oldest = svgSourceCache . keys ( ) . next ( ) . value ;
113+ if ( oldest !== undefined ) svgSourceCache . delete ( oldest ) ;
114+ }
115+ svgSourceCache . set ( markup , pending ) ;
116+ }
117+ const fetched = await pending ;
118+ if ( fetched !== null ) {
119+ sourceMarkup = fetched ;
120+ } else {
108121 // Preserve the original source when a remote host blocks CORS. The
109122 // marker still renders, although its QGIS color parameters cannot be
110123 // resolved without access to the SVG text.
0 commit comments