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 @@
@@ -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 @@
@@ -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