([]);
-
+}: NoteContentProps) {
// Process the content to render mentions, links, etc.
- useEffect(() => {
- const processContent = async () => {
- const text = event.content;
-
- // Regular expressions for different patterns
- const urlRegex = /(https?:\/\/[^\s]+)/g;
- const nostrRegex = /nostr:(npub1|note1|nprofile1|nevent1)([a-z0-9]+)/g;
- const hashtagRegex = /#(\w+)/g;
-
- // Split the content by these patterns
- let lastIndex = 0;
- const parts: React.ReactNode[] = [];
-
- // Process URLs
- const processUrls = () => {
- text.replace(urlRegex, (match, url, index) => {
- if (index > lastIndex) {
- parts.push(text.substring(lastIndex, index));
- }
-
- parts.push(
-
- {url}
-
- );
-
- lastIndex = index + match.length;
- return match;
- });
- };
-
- // Process Nostr references
- const processNostrRefs = () => {
- text.replace(nostrRegex, (match, prefix, datastring, index) => {
- if (index > lastIndex) {
- parts.push(text.substring(lastIndex, index));
- }
-
- try {
- const nostrId = `${prefix}${datastring}`;
- const decoded = nip19.decode(nostrId);
-
- if (decoded.type === 'npub') {
- const pubkey = decoded.data as string;
- parts.push(
-
- );
- } else if (decoded.type === 'note') {
- parts.push(
-
- note
-
- );
- } else {
- // For other types, just show as a link
- parts.push(
-
- {match}
-
- );
- }
- } catch (e) {
- // If decoding fails, just render as text
- parts.push(match);
- }
-
- lastIndex = index + match.length;
- return match;
- });
- };
-
- // Process hashtags
- const processHashtags = () => {
- text.replace(hashtagRegex, (match, tag, index) => {
- if (index > lastIndex) {
- parts.push(text.substring(lastIndex, index));
- }
-
- parts.push(
-
- #{tag}
-
- );
-
- lastIndex = index + match.length;
- return match;
- });
- };
-
- // Run all processors
- processUrls();
- processNostrRefs();
- processHashtags();
-
- // Add any remaining text
- if (lastIndex < text.length) {
- parts.push(text.substring(lastIndex));
- }
-
- // If no special content was found, just use the plain text
- if (parts.length === 0) {
- parts.push(text);
- }
-
- setContent(parts);
- };
+ const content = useMemo(() => {
+ const text = event.content;
- processContent();
+ // Regex to find URLs, Nostr references, and hashtags
+ const regex = /(https?:\/\/[^\s]+)|nostr:(npub1|note1|nprofile1|nevent1)([a-z0-9]+)|(#\w+)/g;
+
+ const parts: React.ReactNode[] = [];
+ let lastIndex = 0;
+ let match: RegExpExecArray | null;
+ let keyCounter = 0;
+
+ while ((match = regex.exec(text)) !== null) {
+ const [fullMatch, url, nostrPrefix, nostrData, hashtag] = match;
+ const index = match.index;
+
+ // Add text before this match
+ if (index > lastIndex) {
+ parts.push(text.substring(lastIndex, index));
+ }
+
+ if (url) {
+ // Handle URLs
+ parts.push(
+
+ {url}
+
+ );
+ } else if (nostrPrefix && nostrData) {
+ // Handle Nostr references
+ try {
+ const nostrId = `${nostrPrefix}${nostrData}`;
+ const decoded = nip19.decode(nostrId);
+
+ if (decoded.type === 'npub') {
+ const pubkey = decoded.data;
+ parts.push(
+
+ );
+ } else {
+ // For other types, just show as a link
+ parts.push(
+
+ {fullMatch}
+
+ );
+ }
+ } catch (e) {
+ // If decoding fails, just render as text
+ parts.push(fullMatch);
+ }
+ } else if (hashtag) {
+ // Handle hashtags
+ const tag = hashtag.slice(1); // Remove the #
+ parts.push(
+
+ {hashtag}
+
+ );
+ }
+
+ lastIndex = index + fullMatch.length;
+ }
+
+ // Add any remaining text
+ if (lastIndex < text.length) {
+ parts.push(text.substring(lastIndex));
+ }
+
+ // If no special content was found, just use the plain text
+ if (parts.length === 0) {
+ parts.push(text);
+ }
+
+ return parts;
}, [event]);
-
+
return (
{content.length > 0 ? content : event.content}
@@ -156,11 +116,12 @@ export function NoteContent({
// Helper component to display user mentions
function NostrMention({ pubkey }: { pubkey: string }) {
const author = useAuthor(pubkey);
- const displayName = author.data?.metadata?.name || pubkey.slice(0, 8);
-
+ const npub = nip19.npubEncode(pubkey);
+ const displayName = author.data?.metadata?.name ?? npub.slice(0, 8);
+
return (
@{displayName}