feat: Add renderTextWithLinkedTags utility to hyperlink hashtags in text content

This commit is contained in:
2025-05-22 21:56:56 +02:00
parent 7d4437cdec
commit 75f500998f
3 changed files with 60 additions and 2 deletions

View File

@@ -14,6 +14,7 @@ import ViewCopyButton from "./ViewCopyButton"
import type { Event as NostrEvent } from "nostr-tools"
import ZapButton from "./ZapButton"
import Image from "next/image"
import { renderTextWithLinkedTags } from "@/utils/textUtils"
interface KIND20CardProps {
pubkey: string
@@ -95,7 +96,7 @@ const KIND20Card: React.FC<KIND20CardProps> = ({
</div>
</div>
<div className="p-4">
<div className="break-word overflow-hidden">{text}</div>
<div className="break-word overflow-hidden">{renderTextWithLinkedTags(text, tags)}</div>
<hr className="my-4" />
<div className="space-x-4 flex justify-between items-start">
<div className="flex space-x-4">

View File

@@ -31,6 +31,7 @@ import Link from 'next/link';
import ViewCopyButton from './ViewCopyButton';
import { Event as NostrEvent } from "nostr-tools";
import ZapButton from './ZapButton';
import { renderTextWithLinkedTags } from '@/utils/textUtils';
interface NoteCardProps {
pubkey: string;
@@ -142,7 +143,7 @@ const NoteCard: React.FC<NoteCardProps> = ({ pubkey, text, eventId, tags, event,
}
<br />
<div className='break-word overflow-hidden'>
{textWithoutImage}
{renderTextWithLinkedTags(textWithoutImage, tags)}
</div>
</div>
<hr />

56
utils/textUtils.tsx Normal file
View File

@@ -0,0 +1,56 @@
import React, { ReactNode } from 'react';
import Link from 'next/link';
/**
* Renders text content with hyperlinked hashtags
* @param content The text content that may contain hashtags
* @param eventTags The tags array from a Nostr event
* @returns An array of text and link elements
*/
export function renderTextWithLinkedTags(content: string, eventTags: string[][]): ReactNode[] {
if (!content) return [];
// Extract all hashtags from the event tags
const eventHashtags = eventTags
.filter((tag) => tag[0] === "t")
.map((tag) => tag[1].toLowerCase());
// Find hashtags in the content with regex
const hashtagRegex = /#(\w+)/g;
let lastIndex = 0;
const result: ReactNode[] = [];
let match;
while ((match = hashtagRegex.exec(content)) !== null) {
const hashtag = match[1].toLowerCase();
const fullHashtag = match[0]; // #hashtag
const matchIndex = match.index;
// Add text before the hashtag
if (matchIndex > lastIndex) {
result.push(content.substring(lastIndex, matchIndex));
}
// Check if this hashtag exists in the event tags
if (eventHashtags.includes(hashtag)) {
// Create a link for matching hashtags
result.push(
<Link href={`/tag/${hashtag}`} key={`${hashtag}-${matchIndex}`} className="text-blue-500 hover:underline">
{fullHashtag}
</Link>
);
} else {
// Add the hashtag without a link if it's not in the tags
result.push(fullHashtag);
}
lastIndex = matchIndex + fullHashtag.length;
}
// Add any remaining text
if (lastIndex < content.length) {
result.push(content.substring(lastIndex));
}
return result;
}