Skip to content

Commit 9b54e63

Browse files
jaiakashcoderabbitai[bot]arkid15r
authored
fix: clickable org if there is any @ text in user bio (OWASP#951)
* fix: clickable org if there is any @ text in user bio Signed-off-by: Akash Jaiswal <akashjaiswal3846@gmail.com> * fix: unit tests Signed-off-by: Akash Jaiswal <akashjaiswal3846@gmail.com> * fix: trailing punctuation in github user name Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix: remove dot at end if its present in username Signed-off-by: Akash Jaiswal <akashjaiswal3846@gmail.com> * fix: all puntuation to be excluded from link Signed-off-by: Akash Jaiswal <akashjaiswal3846@gmail.com> --------- Signed-off-by: Akash Jaiswal <akashjaiswal3846@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com>
1 parent 2f307c7 commit 9b54e63

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

frontend/__tests__/unit/data/mockUserDetails.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export const mockUserDetailsData = {
44
name: 'Test User',
55
avatarUrl: 'https://example.com/avatar.jpg',
66
url: 'https://github.com/testuser',
7-
bio: 'This is a test user',
7+
bio: 'Test @User',
88
company: 'Test Company',
99
location: 'Test Location',
1010
email: 'testuser@example.com',

frontend/__tests__/unit/pages/UserDetails.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ describe('UserDetailsPage', () => {
7272

7373
expect(screen.getByText('Test User')).toBeInTheDocument()
7474
expect(screen.getByText(`@testuser`)).toBeInTheDocument()
75-
expect(screen.getByText('This is a test user')).toBeInTheDocument()
75+
expect(screen.getByText('Test')).toBeInTheDocument()
76+
expect(screen.getByText('@User')).toBeInTheDocument()
7677
expect(screen.getByText('Test Company')).toBeInTheDocument()
7778
expect(screen.getByText('Test Location')).toBeInTheDocument()
7879
})

frontend/src/pages/UserDetails.tsx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,30 @@ const UserDetailsPage: React.FC = () => {
9191
)
9292
}
9393

94+
const formattedBio = user?.bio?.split(' ').map((word, index) => {
95+
// Regex to match GitHub usernames, but if last character is not a word character or @, it's a punctuation
96+
let mentionMatch = word.match(/^@([\w-]+(?:\.[\w-]+)*)([^\w@])?$/)
97+
if (mentionMatch && mentionMatch.length > 1) {
98+
let username = mentionMatch[1]
99+
let punctuation = mentionMatch[2] || ''
100+
return (
101+
<React.Fragment key={index}>
102+
<Link
103+
href={`https://github.com/${username}`}
104+
target="_blank"
105+
rel="noopener noreferrer"
106+
className="text-blue-500 hover:underline"
107+
>
108+
@{username}
109+
</Link>
110+
{punctuation}
111+
<span> </span>
112+
</React.Fragment>
113+
)
114+
}
115+
return <span key={index}>{word} </span>
116+
})
117+
94118
return (
95119
<MetadataManager pageTitle={user?.name || user?.login} description={user?.bio} url={user.url}>
96120
<div className="mt-24 min-h-screen w-full p-4">
@@ -150,7 +174,9 @@ const UserDetailsPage: React.FC = () => {
150174
</div>
151175
</div>
152176
<div className="px-6 py-6">
153-
{user.bio && <p className="text-lg text-gray-700 dark:text-gray-300">{user.bio}</p>}
177+
{user.bio && (
178+
<p className="text-lg text-gray-700 dark:text-gray-300">{formattedBio}</p>
179+
)}
154180
<div className="mt-4 space-y-3">
155181
{user.company && (
156182
<div className="flex items-center space-x-2 text-gray-600 dark:text-gray-400">
@@ -229,7 +255,6 @@ const UserDetailsPage: React.FC = () => {
229255
</div>
230256
</div>
231257
)}
232-
233258
{user.releases && user.releases.length > 0 && (
234259
<div className="space-y-4">
235260
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">

0 commit comments

Comments
 (0)