Skip to content

Conversation

@AnshulJagotra
Copy link
Contributor

Fixes #1242

Problem Description
Climb and area names containing ampersands (&) or other HTML entities were rendered incorrectly in the frontend.
Currently, these entities (&, <, >, etc.) were displayed literally instead of being decoded, causing route names and climb/area names to appear incorrectly.

Solution

Added a safeDecode utility function in src/js/utils.ts to safely decode common HTML entities.

Updated the following components to use safeDecode before rendering names:

ClimbData.tsx

Area page (page.tsx)

ClimbListForm.tsx

Ensures proper display in both client-side rendering (CSR) and server-side rendering (SSR).

Idempotent solution: safe even if backend resolves encoding in the future.

Testing

Verified that climb and area names with & or other HTML entities display correctly in the UI.

Verified SSR pages render correctly without crashing.

User-facing changes

Climb and area names now display correctly (& instead of &) on all pages.

Backwards-incompatible changes

None. This change only affects frontend rendering logic; existing data and backend APIs remain unchanged.

Optional / Suggestion

If the backend (REST or GraphQL API) is encoding HTML entities before sending names, it may be preferable to send plain text directly.

Frontend will continue to work safely even if the backend implements this change in the future.

Copy link
Contributor

@mikeschen mikeschen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that these functions are created, but where are they called? @AnshulJagotra

@AnshulJagotra
Copy link
Contributor Author

Thanks @mikeschen, you were right — the safeDecode function was created but not used in the components.
I’ve now updated ClimbData.tsx, Area page.tsx, and ClimbListForm.tsx to call safeDecode when rendering names.

@mikeschen mikeschen requested a review from Copilot October 28, 2025 01:49
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes the rendering of HTML entities in climb and area names throughout the application. Previously, names containing ampersands and other HTML entities were displayed as their encoded forms (e.g., &amp; instead of &).

  • Added a safeDecode utility function that safely decodes HTML entities in both client-side and server-side rendering contexts
  • Updated components to decode names before display: ClimbData, Area page, and ClimbListForm
  • Ensured consistent rendering across SSR and CSR environments

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/js/utils.ts Added safeDecode and decodeAmpersand utility functions for HTML entity decoding
src/app/(default)/editArea/[slug]/general/components/climb/ClimbListForm.tsx Applied safeDecode to climb names in the climb list display and toolbar
src/app/(default)/climb/[[...slug]]/components/ClimbData.tsx Applied safeDecode to climb name in the main heading
src/app/(default)/area/[[...slug]]/page.tsx Applied safeDecode to area names in multiple locations including page actions and metadata

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +361 to +364
export const decodeAmpersand = (s: string): string => {
if (s == null) return ''
return s.replace(/&amp;/g, '&')
}
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The decodeAmpersand function is exported but never used in the codebase. Since safeDecode provides the same functionality plus additional entity decoding, consider removing this unused export to reduce maintenance burden.

Suggested change
export const decodeAmpersand = (s: string): string => {
if (s == null) return ''
return s.replace(/&amp;/g, '&')
}

Copilot uses AI. Check for mistakes.
Comment on lines +362 to +367
if (s == null) return ''
return s.replace(/&amp;/g, '&')
}

export const safeDecode = (s: string): string => {
if (s == null) return ''
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use strict equality (===) instead of loose equality (==) for null checks. The current check will match both null and undefined, which may be unintended. Replace with if (s == null || s === undefined) or if (s == null) depending on the intended behavior, but prefer === for consistency with TypeScript best practices.

Suggested change
if (s == null) return ''
return s.replace(/&amp;/g, '&')
}
export const safeDecode = (s: string): string => {
if (s == null) return ''
if (s === null || s === undefined) return ''
return s.replace(/&amp;/g, '&')
}
export const safeDecode = (s: string): string => {
if (s === null || s === undefined) return ''

Copilot uses AI. Check for mistakes.
}

export const safeDecode = (s: string): string => {
if (s == null) return ''
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use strict equality (===) instead of loose equality (==) for null checks. Replace with explicit null/undefined checks using strict equality for consistency with TypeScript best practices.

Suggested change
if (s == null) return ''
if (s === null || s === undefined) return ''

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ampersands in route names get mangled

2 participants