- {event.content}
+ {@html parsedContent}
{#if shouldTruncate}
@@ -897,7 +900,9 @@
- {notification.content || "No content"}
+ {#await parseBasicmarkup(notification.content || "No content") then parsed}
+ {@html parsed}
+ {/await}
@@ -934,7 +939,9 @@
- {replyToMessage.content || "No content"}
+ {#await parseBasicmarkup(replyToMessage.content || "No content") then parsed}
+ {@html parsed}
+ {/await}
diff --git a/src/lib/utils/markup/basicMarkupParser.ts b/src/lib/utils/markup/basicMarkupParser.ts
index 3526861..02925ec 100644
--- a/src/lib/utils/markup/basicMarkupParser.ts
+++ b/src/lib/utils/markup/basicMarkupParser.ts
@@ -7,6 +7,7 @@ import {
processImageWithReveal,
processMediaUrl,
processNostrIdentifiersInText,
+ processAllNostrIdentifiers,
processWebSocketUrls,
processWikilinks,
stripTrackingParams,
@@ -251,6 +252,7 @@ export async function parseBasicmarkup(text: string): Promise {
// Process Nostr identifiers last
processedText = await processNostrIdentifiersInText(processedText);
+ processedText = processAllNostrIdentifiers(processedText);
// Replace wikilinks
processedText = processWikilinks(processedText);
diff --git a/src/lib/utils/markup/markupServices.ts b/src/lib/utils/markup/markupServices.ts
index 3ed8a78..52532f8 100644
--- a/src/lib/utils/markup/markupServices.ts
+++ b/src/lib/utils/markup/markupServices.ts
@@ -180,6 +180,112 @@ export function processNostrIdentifiersWithEmbeddedEvents(
return processedText;
}
+/**
+ * Shared service for processing all nostr identifiers (both profiles and events)
+ * Creates clickable links for all nostr identifiers
+ */
+export function processAllNostrIdentifiers(text: string): string {
+ let processedText = text;
+
+ // Pattern for prefixed nostr identifiers (nostr:npub1, nostr:note1, etc.)
+ // This handles both full identifiers and partial ones that might appear in content
+ const prefixedNostrPattern = /nostr:(npub|nprofile|note|nevent|naddr)[a-zA-Z0-9]{20,}/g;
+
+ // Pattern for bare nostr identifiers (npub1, note1, nevent1, naddr1)
+ // Exclude matches that are part of URLs to avoid breaking existing links
+ const bareNostrPattern = /(?= 0; i--) {
+ const match = prefixedMatches[i];
+ const [fullMatch] = match;
+ const matchIndex = match.index ?? 0;
+
+ // Create shortened display text
+ const identifier = fullMatch.replace('nostr:', '');
+ const displayText = `${identifier.slice(0, 8)}...${identifier.slice(-4)}`;
+
+ // Create clickable link
+ const replacement = `${displayText}`;
+
+ // Replace the match in the text
+ processedText = processedText.slice(0, matchIndex) + replacement +
+ processedText.slice(matchIndex + fullMatch.length);
+ }
+
+ // Process bare nostr identifiers
+ const bareMatches = Array.from(processedText.matchAll(bareNostrPattern));
+
+ // Process them in reverse order to avoid index shifting issues
+ for (let i = bareMatches.length - 1; i >= 0; i--) {
+ const match = bareMatches[i];
+ const [fullMatch] = match;
+ const matchIndex = match.index ?? 0;
+
+ // Create shortened display text
+ const displayText = `${fullMatch.slice(0, 8)}...${fullMatch.slice(-4)}`;
+
+ // Create clickable link with nostr: prefix for the href
+ const replacement = `${displayText}`;
+
+ // Replace the match in the text
+ processedText = processedText.slice(0, matchIndex) + replacement +
+ processedText.slice(matchIndex + fullMatch.length);
+ }
+
+ // Also handle any remaining truncated prefixed identifiers that might be cut off or incomplete
+ const truncatedPrefixedPattern = /nostr:(npub|nprofile|note|nevent|naddr)[a-zA-Z0-9]{8,}/g;
+ const truncatedPrefixedMatches = Array.from(processedText.matchAll(truncatedPrefixedPattern));
+
+ for (let i = truncatedPrefixedMatches.length - 1; i >= 0; i--) {
+ const match = truncatedPrefixedMatches[i];
+ const [fullMatch] = match;
+ const matchIndex = match.index ?? 0;
+
+ // Skip if this was already processed by the main pattern
+ if (fullMatch.length >= 30) continue; // Full identifiers are at least 30 chars
+
+ // Create display text for truncated identifiers
+ const identifier = fullMatch.replace('nostr:', '');
+ const displayText = identifier.length > 12 ? `${identifier.slice(0, 8)}...${identifier.slice(-4)}` : identifier;
+
+ // Create clickable link
+ const replacement = `${displayText}`;
+
+ // Replace the match in the text
+ processedText = processedText.slice(0, matchIndex) + replacement +
+ processedText.slice(matchIndex + fullMatch.length);
+ }
+
+ // Handle truncated bare identifiers
+ const truncatedBarePattern = /(?= 0; i--) {
+ const match = truncatedBareMatches[i];
+ const [fullMatch] = match;
+ const matchIndex = match.index ?? 0;
+
+ // Skip if this was already processed by the main pattern
+ if (fullMatch.length >= 30) continue; // Full identifiers are at least 30 chars
+
+ // Create display text for truncated identifiers
+ const displayText = fullMatch.length > 12 ? `${fullMatch.slice(0, 8)}...${fullMatch.slice(-4)}` : fullMatch;
+
+ // Create clickable link
+ const replacement = `${displayText}`;
+
+ // Replace the match in the text
+ processedText = processedText.slice(0, matchIndex) + replacement +
+ processedText.slice(matchIndex + fullMatch.length);
+ }
+
+ return processedText;
+}
+
/**
* Shared service for processing emoji shortcodes
*/
diff --git a/src/routes/events/+page.svelte b/src/routes/events/+page.svelte
index c358811..287764f 100644
--- a/src/routes/events/+page.svelte
+++ b/src/routes/events/+page.svelte
@@ -21,6 +21,7 @@
import { getEventType } from "$lib/utils/mime";
import ViewPublicationLink from "$lib/components/util/ViewPublicationLink.svelte";
import { checkCommunity } from "$lib/utils/search_utility";
+ import { parseBasicmarkup } from "$lib/utils/markup/basicMarkupParser";
import { userStore } from "$lib/stores/userStore";
import {
@@ -751,10 +752,9 @@
- {result.content.slice(0, 200)}
- {#if result.content.length > 200}
- ...
- {/if}
+ {#await parseBasicmarkup(result.content.slice(0, 200) + (result.content.length > 200 ? "..." : "")) then parsed}
+ {@html parsed}
+ {/await}
{/if}
{/if}
@@ -938,10 +938,9 @@
- {result.content.slice(0, 200)}
- {#if result.content.length > 200}
- ...
- {/if}
+ {#await parseBasicmarkup(result.content.slice(0, 200) + (result.content.length > 200 ? "..." : "")) then parsed}
+ {@html parsed}
+ {/await}
{/if}
{/if}
@@ -1111,10 +1110,9 @@
- {result.content.slice(0, 200)}
- {#if result.content.length > 200}
- ...
- {/if}
+ {#await parseBasicmarkup(result.content.slice(0, 200) + (result.content.length > 200 ? "..." : "")) then parsed}
+ {@html parsed}
+ {/await}
{/if}
{/if}