diff --git a/README.md b/README.md index c120f4a..74f1c4b 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,7 @@ const props: supportUsButtonProps = { name: "", // ← your organization name description: "", // ← short org description logo: { src: "", alt: "" }, // ← Add file path to src and alt text for accessibility. Note: Accepts a string path/url. + url: "https://example.com", // ← optional: if a valid https:// URL is provided, the logo becomes clickable projectInformation: { name: "", // ← your project name description: "",// ← short project description @@ -334,6 +335,7 @@ Information about the organization and project. | `name` | string | Yes | Organization name | | `description` | string | Yes | Organization description | | `logo` | `Image` / string | No | Organization logo | +| `url` | string | No | Organization link | | `projectInformation` | `projectInformation` | No | Project details | diff --git a/src/components/SupportUsButton.tsx b/src/components/SupportUsButton.tsx index c9b7278..e380029 100644 --- a/src/components/SupportUsButton.tsx +++ b/src/components/SupportUsButton.tsx @@ -48,6 +48,16 @@ function getButtonClasses(buttonVariant: ButtonVariant): string { return `${base} bg-primary hover:bg-primary/90 text-black font-black py-4 transition-all active:scale-[0.98] shadow-lg shadow-primary/20`; } +// Helper function to validate URLs and prevent XSS through 'javascript:' protocol +function validateUrl(url?: string): string | undefined { + if (!url) return undefined; + const lowerUrl = url.toLowerCase(); + if (lowerUrl.startsWith("http://") || lowerUrl.startsWith("https://")) { + return url; + } + return undefined; +} + // Main component function that renders the support us button, taking in various props for customization and rendering different sections such as hero, organization information, sponsors, and call-to-action based on the provided data and selected theme and button variant function SupportUsButton({ Theme = "AOSSIE", @@ -70,6 +80,21 @@ function SupportUsButton({ }, buttonVariant = "AOSSIE", }: supportUsButtonProps): React.JSX.Element { + const validatedUrl = validateUrl(organizationInformation?.url); + const logoContent = + typeof organizationInformation.logo === "string" ? ( + + {organizationInformation.logo} + + ) : ( + {organizationInformation.logo?.alt} + ); return ( // Container for the support us button, with dynamic classes based on the selected theme and custom class names
- {typeof organizationInformation.logo === "string" ? ( - - - {organizationInformation.logo} - - - ) : ( - {organizationInformation.logo?.alt} - )} + +
+ {organizationInformation?.logo && + (validatedUrl ? ( + + {logoContent} + + ) : ( + logoContent + ))}
{/* Organization name and description */} @@ -454,4 +476,4 @@ function SupportUsButton({ ); } -export default SupportUsButton; +export default SupportUsButton; \ No newline at end of file diff --git a/src/types/index.ts b/src/types/index.ts index eb5e896..112abf9 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -55,7 +55,7 @@ export type organizationInformation = { /** Organization logo */ logo?: Image | string; - + url?: string; projectInformation?: projectInformation; };