@@ -217,69 +217,103 @@ class CoCreateFileSystem {
217217
218218 let contentType = file [ "content-type" ] || "text/html" ;
219219
220- // Remove redundant handling for `src.src` in font file processing
221- if ( contentType . startsWith ( "font/" ) || / \. ( w o f f 2 ? | t t f | o t f ) $ / i. test ( pathname ) ) {
222- try {
223- if ( typeof src === "string" ) {
224- if ( src . startsWith ( "data:font/" ) ) {
225- src = src . substring ( src . indexOf ( "," ) + 1 ) ;
220+ // Normalize and decode src based on content-type and pathname.
221+ async function normalizeSrc ( src , contentType , pathname ) {
222+ const isBase64Only = ( s ) =>
223+ typeof s === "string" && / ^ [ A - Z a - z 0 - 9 + / ] + = { 0 , 2 } $ / . test ( s ) && s . length % 4 === 0 ;
224+
225+ const parseDataUri = ( s ) => {
226+ // returns { mime, isBase64, data } or null
227+ const m = / ^ d a t a : ( [ ^ ; ] + ) ( ; b a s e 6 4 ) ? , ( .* ) $ / is. exec ( s ) ;
228+ if ( ! m ) return null ;
229+ return { mime : m [ 1 ] . toLowerCase ( ) , isBase64 : ! ! m [ 2 ] , data : m [ 3 ] } ;
230+ } ;
231+
232+ // Fonts: data:font/...;base64 or plain base64 -> Buffer
233+ if ( contentType . startsWith ( "font/" ) || / \. ( w o f f 2 ? | t t f | o t f ) $ / i. test ( pathname ) ) {
234+ if ( Buffer . isBuffer ( src ) ) return src ;
235+ if ( typeof src !== "string" ) throw new Error ( "Invalid font src" ) ;
236+ const d = parseDataUri ( src ) ;
237+ if ( d && d . isBase64 ) return Buffer . from ( d . data , "base64" ) ;
238+ // maybe stored as bare base64
239+ if ( isBase64Only ( src ) ) return Buffer . from ( src , "base64" ) ;
240+ throw new Error ( "Font data is not valid base64 or data URI" ) ;
241+ }
242+
243+ // Data URIs
244+ if ( typeof src === "string" ) {
245+ const d = parseDataUri ( src ) ;
246+ if ( d ) {
247+ // SVG: decode to utf8 string so browsers render SVG correctly
248+ if ( d . mime === "image/svg+xml" ) {
249+ if ( d . isBase64 ) return Buffer . from ( d . data , "base64" ) . toString ( "utf8" ) ;
250+ // URI-encoded SVG payload
251+ try {
252+ return decodeURIComponent ( d . data ) ;
253+ } catch ( _ ) {
254+ return d . data ;
255+ }
226256 }
227- if ( / ^ ( [ A - Z a - z 0 - 9 + / ] + = { 0 , 2 } ) $ / . test ( src ) ) {
228- // Decode base64-encoded font data
229- src = Buffer . from ( src , "base64" ) ;
230- } else {
231- throw new Error ( "Font data is not valid base64" ) ;
257+ // Raster images -> Buffer
258+ if ( / ^ i m a g e \/ ( p n g | j p e ? g | w e b p | b m p | g i f ) $ / i. test ( d . mime ) ) {
259+ if ( d . isBase64 ) return Buffer . from ( d . data , "base64" ) ;
260+ }
261+ // If it's a text data URI (e.g., xml) and not base64, return decoded text
262+ if ( ! d . isBase64 ) {
263+ try {
264+ return decodeURIComponent ( d . data ) ;
265+ } catch ( _ ) {
266+ return d . data ;
267+ }
232268 }
233- } else {
234- throw new Error ( "Font data is not a valid base64 string" ) ;
235269 }
236- } catch ( err ) {
237- console . error ( "Error processing font file:" , {
238- message : err . message ,
239- contentType,
240- srcType : typeof src
241- } ) ;
242- let pageNotFound = await getDefaultFile ( "/404.html" ) ;
243- return sendResponse ( pageNotFound . object [ 0 ] . src , 404 , {
244- "Content-Type" : "text/html"
245- } ) ;
246270 }
247- } else if (
248- / ^ d a t a : i m a g e \/ [ a - z A - Z 0 - 9 + . - ] + ; b a s e 6 4 , ( [ A - Z a - z 0 - 9 + / ] + = { 0 , 2 } ) $ / . test (
249- src
250- )
251- ) {
252- src = src . replace ( / ^ d a t a : i m a g e \/ ( p n g | j p e g | j p g ) ; b a s e 6 4 , / , "" ) ;
253- src = Buffer . from ( src , "base64" ) ;
254- } else if ( / ^ ( [ A - Z a - z 0 - 9 + / ] + = { 0 , 2 } ) $ / . test ( src ) ) {
255- src = Buffer . from ( src , "base64" ) ;
256- } else if ( contentType === "text/html" ) {
257- try {
258- let data = { } ;
259271
260- // pass detected theme (may be undefined) into server-side renderer
261- src = await this . render . HTML (
272+ // Plain base64-only string: decode to Buffer only for binary content types
273+ if ( isBase64Only ( src ) ) {
274+ if (
275+ contentType . startsWith ( "image/" ) ||
276+ contentType . startsWith ( "font/" ) ||
277+ contentType === "application/octet-stream"
278+ ) {
279+ return Buffer . from ( src , "base64" ) ;
280+ }
281+ // textual content kept as-is
282+ return src ;
283+ }
284+
285+ // HTML rendering
286+ if ( contentType === "text/html" ) {
287+ return await this . render . HTML (
262288 file ,
263289 organization ,
264290 urlObject ,
265291 langRegion ,
266292 lang ,
267293 theme
268294 ) ;
269- } catch ( err ) {
270- console . warn ( "server-side-render: " + err . message ) ;
271295 }
272- } else if (
273- contentType === "text/xml" ||
274- contentType === "application/xml"
275- ) {
276- const protocol = "https://" ;
277- src = src . replaceAll ( "{{$host}}" , ` ${ protocol } ${ hostname } ` ) ;
278- } else if ( contentType !== "text/javascript" || contentType === "text/css" ) {
279-
280- console . warn ( `Unknown content type: ${ contentType } ` ) ;
296+
297+ // XML host replacement if src is string
298+ if ( ( contentType === "text/xml" || contentType === " application/xml") && typeof src === "string" ) {
299+ const protocol = "https://" ;
300+ return src . replaceAll ( "{{$host}}" , ` ${ protocol } ${ hostname } ` ) ;
301+ }
302+
303+ // Otherwise return as-is (string, Buffer, object)
304+ return src ;
281305 }
282306
307+ try {
308+ src = await normalizeSrc . call ( this , src , contentType , pathname ) ;
309+ } catch ( err ) {
310+ console . error ( "Error processing file src:" , err && err . message ) ;
311+ let pageNotFound = await getDefaultFile ( "/404.html" ) ;
312+ return sendResponse ( pageNotFound . object [ 0 ] . src , 404 , {
313+ "Content-Type" : "text/html"
314+ } ) ;
315+ }
316+
283317 sendResponse ( src , 200 , { "Content-Type" : contentType } ) ;
284318 this . sitemap . check ( file , hostname ) ;
285319
0 commit comments