@@ -336,7 +336,7 @@ export const climbLeftRightIndexComparator = (a: ClimbType, b: ClimbType): numbe
336336export interface SortableAreaType { metadata : Pick < AreaMetadataType , 'leftRightIndex' | 'areaId' > }
337337
338338export const areaLeftRightIndexComparator = ( a : SortableAreaType , b : SortableAreaType ) : number => {
339- const aIndex = a . metadata . . leftRightIndex ?? - 1
339+ const aIndex = a . metadata . leftRightIndex ?? - 1
340340 const bIndex = b . metadata . leftRightIndex ?? - 1
341341 if ( aIndex < bIndex ) return - 1
342342 else if ( aIndex > bIndex ) return 1
@@ -359,6 +359,22 @@ export const parseUuidAsFirstParam = ({ params }: PageWithCatchAllUuidProps): st
359359}
360360
361361export const decodeAmpersand = ( s : string ) : string => {
362- if ( s == null ) return '' ;
363- return s . replace ( / & a m p ; / g, '&' ) ;
362+ if ( s == null ) return ''
363+ return s . replace ( / & a m p ; / g, '&' )
364+ }
365+
366+ export const safeDecode = ( s : string ) : string => {
367+ if ( s == null ) return ''
368+ if ( typeof window !== 'undefined' ) {
369+ const txt = document . createElement ( 'textarea' )
370+ txt . innerHTML = s
371+ return txt . value
372+ }
373+ // Basic SSR-safe decoding for common entities
374+ return s
375+ . replace ( / & a m p ; / g, '&' )
376+ . replace ( / & l t ; / g, '<' )
377+ . replace ( / & g t ; / g, '>' )
378+ . replace ( / & q u o t ; / g, '"' )
379+ . replace ( / & # 3 9 ; / g, "'" )
364380}
0 commit comments