import { ShoppingCart } from "lucide-react"; import { BookmarkTypes, ZBookmark } from "@karakeep/shared/types/bookmarks"; import { ContentRenderer } from "./types"; function extractAmazonProductInfo( url: string, ): { asin: string; domain: string } | null { const patterns = [ // Standard product URLs /amazon\.([a-z.]+)\/.*\/dp\/([A-Z0-9]{10})/, /amazon\.([a-z.]+)\/dp\/([A-Z0-9]{10})/, // Shortened URLs /amazon\.([a-z.]+)\/gp\/product\/([A-Z0-9]{10})/, // Mobile URLs /amazon\.([a-z.]+)\/.*\/product\/([A-Z0-9]{10})/, // International variations /amazon\.([a-z.]+)\/.*\/([A-Z0-9]{10})/, ]; for (const pattern of patterns) { const match = url.match(pattern); if (match) { return { domain: match[1], asin: match[2], }; } } return null; } function canRenderAmazon(bookmark: ZBookmark): boolean { if (bookmark.content.type !== BookmarkTypes.LINK) { return false; } const url = bookmark.content.url; return extractAmazonProductInfo(url) !== null; } function AmazonRendererComponent({ bookmark }: { bookmark: ZBookmark }) { if (bookmark.content.type !== BookmarkTypes.LINK) { return null; } const productInfo = extractAmazonProductInfo(bookmark.content.url); if (!productInfo) { return null; } const { title, description, imageUrl } = bookmark.content; return (
{/* Product Image */} {imageUrl && (
{/* oxlint-disable-next-line no-img-element */} {title
)} {/* Product Info Card */}
{/* Title */} {title && (

{title}

)} {/* Description */} {description && (

{description}

)} {/* Product Details */}
ASIN: {productInfo.asin}
Domain: amazon.{productInfo.domain}
{/* Action Buttons */}
{/* oxlint-disable-next-line no-html-link-for-pages */} View on Amazon {/* oxlint-disable-next-line no-html-link-for-pages */} Direct Link
{/* Amazon Disclaimer */}

Product information from Amazon. Prices and availability may vary.

); } export const amazonRenderer: ContentRenderer = { id: "amazon", name: "Amazon Product", icon: ShoppingCart, canRender: canRenderAmazon, component: AmazonRendererComponent, priority: 10, };