);
}
// Parse the HTML to extract detailed tweet information and media
const parser = new DOMParser();
const doc = parser.parseFromString(tweetData.html, 'text/html');
const blockquote = doc.querySelector('blockquote');
// Extract tweet text (remove attribution line)
const fullText = blockquote?.textContent || '';
const tweetText = fullText.replace(/- .* \(@.*\).*$/, '').trim();
// Extract username from author_url (e.g., https://twitter.com/username)
const username = tweetData.author_url ? tweetData.author_url.split('/').pop() : '';
// Extract any links from the tweet
const links = Array.from(blockquote?.querySelectorAll('a') || [])
.map(link => ({
url: link.href,
text: link.textContent || link.href
}))
.filter(link => !link.url.includes('twitter.com') && !link.url.includes('x.com'));
// Format time (simulated - we don't have real timestamp from oEmbed)
const formatTime = () => {
return 'on X'; // Simplified since we don't have actual timestamp
};
const truncateText = (text: string, maxLength: number = 600) => {
if (text.length <= maxLength) return text;
return text.slice(0, maxLength) + '...';
};
// Profile picture URL using Unavatar service.
// The hub used to proxy this via `useProxiedImageUrl` (chat runtime), but
// docs / blog pages don't mount a chat runtime, so we fetch unavatar
// directly. Embedders that need a proxy can register a runtime later.
const getProfilePicUrl = (username: string | undefined) => {
if (!username) return '';
return `https://unavatar.io/twitter/${username}`;
};
return (
{/* Header with Profile Picture */}
{/* User Profile Picture */}
{
// Simple fallback without state updates
const target = e.target as HTMLImageElement;
target.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0yMCAyMXYtMmE0IDQgMCAwIDAtNC00SDhhNCA0IDAgMCAwLTQgNHYyIi8+PGNpcmNsZSBjeD0iMTIiIGN5PSI3IiByPSI0Ii8+PC9zdmc+';
}}
/>