--- interface Props { url: string; showArchive?: boolean; title?: string; description?: string; siteName?: string; } const { url, showArchive = true} = Astro.props; const siteMetadata = { title: Astro.props.title || '', description: Astro.props.description || '', siteName: Astro.props.siteName || '', image: '', domain: new URL(url).hostname || '' }; // Get metadata from the URL async function fetchMetadata(url: string) { try { const response = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0 (compatible; LinkCard/1.0)' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const html = await response.text(); // 提取元数据 const titleMatch = html.match(/]*>([^<]+)<\/title>/i); const descriptionMatch = html.match(/]+name=["']description["'][^>]+content=["']([^"']+)["']/i) || html.match(/]+property=["']og:description["'][^>]+content=["']([^"']+)["']/i); const imageMatch = html.match(/]+property=["']og:image["'][^>]+content=["']([^"']+)["']/i) || html.match(/]+name=["']twitter:image["'][^>]+content=["']([^"']+)["']/i); const siteNameMatch = html.match(/]+property=["']og:site_name["'][^>]+content=["']([^"']+)["']/i); return { title: titleMatch?.[1]?.trim() || new URL(url).hostname, description: descriptionMatch?.[1]?.trim() || '', image: imageMatch?.[1]?.trim() || '', siteName: siteNameMatch?.[1]?.trim() || new URL(url).hostname, domain: new URL(url).hostname }; } catch (error) { console.warn(`Failed to fetch metadata for ${url}:`, error); const domain = new URL(url).hostname; return { title: domain, description: '', image: '', siteName: domain, domain }; } } // Check if the URL is archived on the Wayback Machine at the build time async function checkArchive(url: string) { try { const archiveUrl = `https://archive.org/wayback/available?url=${encodeURIComponent(url)}`; const response = await fetch(archiveUrl); const data = await response.json(); if (data.archived_snapshots?.closest?.available) { return data.archived_snapshots.closest.url; } } catch (error) { console.warn(`Failed to check archive for ${url}:`, error); } return null; } // extract metadata and archive URL const metadata = Astro.props.title ? siteMetadata : await fetchMetadata(url); const archiveUrl = showArchive ? await checkArchive(url) : null; ---