Browse Source
- Svelte components and snippets that support embedded event rendering are moved to `src/lib/components/embedded_events` dir. - Some now-unused components are removed entirely. - Imports are updated.master
8 changed files with 6 additions and 189 deletions
@ -1,100 +0,0 @@ |
|||||||
<script lang="ts"> |
|
||||||
import { onMount } from "svelte"; |
|
||||||
import { parseBasicmarkup } from "$lib/utils/markup/basicMarkupParser"; |
|
||||||
import EmbeddedEvent from "./EmbeddedEvent.svelte"; |
|
||||||
|
|
||||||
const { |
|
||||||
content, |
|
||||||
nestingLevel = 0, |
|
||||||
} = $props<{ |
|
||||||
content: string; |
|
||||||
nestingLevel?: number; |
|
||||||
}>(); |
|
||||||
|
|
||||||
let parsedContent = $state(""); |
|
||||||
let embeddedEvents = $state<Array<{ |
|
||||||
id: string; |
|
||||||
nostrId: string; |
|
||||||
nestingLevel: number; |
|
||||||
}>>([]); |
|
||||||
|
|
||||||
// Maximum nesting level allowed |
|
||||||
const MAX_NESTING_LEVEL = 3; |
|
||||||
|
|
||||||
// AI-NOTE: 2025-01-24 - Component for rendering content with embedded Nostr events |
|
||||||
// Processes content and replaces nostr: links with EmbeddedEvent components |
|
||||||
|
|
||||||
$effect(() => { |
|
||||||
if (content) { |
|
||||||
processContent(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
async function processContent() { |
|
||||||
try { |
|
||||||
// First parse the basic markup |
|
||||||
parsedContent = await parseBasicmarkup(content); |
|
||||||
|
|
||||||
// Then find and extract embedded events |
|
||||||
extractEmbeddedEvents(); |
|
||||||
} catch (error) { |
|
||||||
console.error("Error processing content:", error); |
|
||||||
parsedContent = content; // Fallback to raw content |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function extractEmbeddedEvents() { |
|
||||||
const nostrPattern = /nostr:(npub|nprofile|note|nevent|naddr)[a-zA-Z0-9]{20,}/g; |
|
||||||
const events: Array<{ |
|
||||||
id: string; |
|
||||||
nostrId: string; |
|
||||||
nestingLevel: number; |
|
||||||
}> = []; |
|
||||||
|
|
||||||
let match; |
|
||||||
while ((match = nostrPattern.exec(parsedContent)) !== null) { |
|
||||||
const nostrId = match[0]; |
|
||||||
const componentId = `embedded-event-${Math.random().toString(36).substr(2, 9)}`; |
|
||||||
|
|
||||||
events.push({ |
|
||||||
id: componentId, |
|
||||||
nostrId, |
|
||||||
nestingLevel: nestingLevel, |
|
||||||
}); |
|
||||||
|
|
||||||
// Replace the nostr: link with a placeholder |
|
||||||
parsedContent = parsedContent.replace( |
|
||||||
nostrId, |
|
||||||
`<div class="embedded-event-placeholder" data-component-id="${componentId}"></div>` |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
embeddedEvents = events; |
|
||||||
} |
|
||||||
|
|
||||||
function renderEmbeddedEvent(eventInfo: { id: string; nostrId: string; nestingLevel: number }) { |
|
||||||
if (eventInfo.nestingLevel >= MAX_NESTING_LEVEL) { |
|
||||||
// At max nesting level, just show the link |
|
||||||
return `<a href="/events?id=${eventInfo.nostrId}" class="text-primary-600 dark:text-primary-500 hover:underline break-all">${eventInfo.nostrId}</a>`; |
|
||||||
} |
|
||||||
|
|
||||||
// Return a placeholder that will be replaced by the component |
|
||||||
return `<div class="embedded-event-placeholder" data-component-id="${eventInfo.id}"></div>`; |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<div class="content-with-embedded-events min-w-0 overflow-hidden"> |
|
||||||
{@html parsedContent} |
|
||||||
|
|
||||||
<!-- Render embedded events --> |
|
||||||
{#each embeddedEvents as eventInfo} |
|
||||||
<div class="my-4 min-w-0 overflow-hidden" data-component-id={eventInfo.id}> |
|
||||||
<EmbeddedEvent |
|
||||||
nostrIdentifier={eventInfo.nostrId} |
|
||||||
nestingLevel={eventInfo.nestingLevel} |
|
||||||
/> |
|
||||||
</div> |
|
||||||
{/each} |
|
||||||
</div> |
|
||||||
|
|
||||||
|
|
||||||
@ -1,83 +0,0 @@ |
|||||||
<script lang="ts"> |
|
||||||
import { onMount } from "svelte"; |
|
||||||
import EmbeddedEvent from "./EmbeddedEvent.svelte"; |
|
||||||
|
|
||||||
const { |
|
||||||
content, |
|
||||||
nestingLevel = 0, |
|
||||||
} = $props<{ |
|
||||||
content: string; |
|
||||||
nestingLevel?: number; |
|
||||||
}>(); |
|
||||||
|
|
||||||
let embeddedEvents = $state<Array<{ |
|
||||||
id: string; |
|
||||||
nostrId: string; |
|
||||||
nestingLevel: number; |
|
||||||
}>>([]); |
|
||||||
|
|
||||||
// AI-NOTE: 2025-01-24 - Component that renders content and replaces embedded event placeholders |
|
||||||
// with actual EmbeddedEvent components |
|
||||||
|
|
||||||
$effect(() => { |
|
||||||
if (content) { |
|
||||||
extractEmbeddedEvents(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
function extractEmbeddedEvents() { |
|
||||||
const placeholderPattern = /<div class="embedded-event-placeholder" data-nostr-id="([^"]+)" data-nesting-level="(\d+)" id="([^"]+)"><\/div>/g; |
|
||||||
const events: Array<{ |
|
||||||
id: string; |
|
||||||
nostrId: string; |
|
||||||
nestingLevel: number; |
|
||||||
}> = []; |
|
||||||
|
|
||||||
let match; |
|
||||||
while ((match = placeholderPattern.exec(content)) !== null) { |
|
||||||
const nostrId = match[1]; |
|
||||||
const level = parseInt(match[2], 10); |
|
||||||
const componentId = match[3]; |
|
||||||
|
|
||||||
// Only process event-related identifiers (note, nevent, naddr) |
|
||||||
if (nostrId.match(/^nostr:(note|nevent|naddr)/)) { |
|
||||||
events.push({ |
|
||||||
id: componentId, |
|
||||||
nostrId, |
|
||||||
nestingLevel: level, |
|
||||||
}); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
embeddedEvents = events; |
|
||||||
} |
|
||||||
|
|
||||||
function renderContent() { |
|
||||||
let renderedContent = content; |
|
||||||
|
|
||||||
// Replace placeholders with component references |
|
||||||
embeddedEvents.forEach(eventInfo => { |
|
||||||
const placeholder = `<div class="embedded-event-placeholder" data-nostr-id="${eventInfo.nostrId}" data-nesting-level="${eventInfo.nestingLevel}" id="${eventInfo.id}"></div>`; |
|
||||||
const componentRef = `<div class="embedded-event-component" data-component-id="${eventInfo.id}"></div>`; |
|
||||||
renderedContent = renderedContent.replace(placeholder, componentRef); |
|
||||||
}); |
|
||||||
|
|
||||||
return renderedContent; |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<div class="embedded-event-renderer"> |
|
||||||
{@html renderContent()} |
|
||||||
|
|
||||||
<!-- Render embedded events --> |
|
||||||
{#each embeddedEvents as eventInfo} |
|
||||||
<div class="my-4" data-component-id={eventInfo.id}> |
|
||||||
<EmbeddedEvent |
|
||||||
nostrIdentifier={eventInfo.nostrId} |
|
||||||
nestingLevel={eventInfo.nestingLevel} |
|
||||||
/> |
|
||||||
</div> |
|
||||||
{/each} |
|
||||||
</div> |
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in new issue