UNPKG

@ai-growth/nextjs

Version:

Seamlessly integrate Sanity CMS with Next.js applications for automated blog routing and rendering

147 lines (146 loc) 4.2 kB
/** * @fileoverview Image Processing Utilities for SEO * * This module provides functions for processing Sanity images * and preparing them for SEO meta tags and structured data. */ /** * Process a Sanity image or string URL for SEO use * * @param image - Sanity image object or string URL * @param baseUrl - Base URL for relative paths * @returns Processed image data for SEO */ export function processImage(image, baseUrl) { if (!image) { return { url: `${baseUrl}/default-og-image.jpg`, alt: 'Default image', width: 1200, height: 630, type: 'image/jpeg', }; } // Handle string URLs if (typeof image === 'string') { const url = image.startsWith('http') ? image : `${baseUrl}${image}`; return { url, alt: 'Image', width: 1200, height: 630, type: getImageTypeFromUrl(url), }; } // Handle Sanity image objects if (image.asset && image.asset._ref) { // Extract Sanity image ID and build URL const imageId = image.asset._ref; const imageUrl = buildSanityImageUrl(imageId, { width: 1200, height: 630, fit: 'crop', format: 'jpg', }); return { url: imageUrl, alt: image.alt || 'Image', width: 1200, height: 630, type: 'image/jpeg', }; } // Fallback to default image return { url: `${baseUrl}/default-og-image.jpg`, alt: 'Default image', width: 1200, height: 630, type: 'image/jpeg', }; } /** * Build a Sanity image URL with transformations * * @param imageRef - Sanity image reference * @param options - Image transformation options * @returns Transformed image URL */ export function buildSanityImageUrl(imageRef, options = {}) { // Extract image details from Sanity reference // Format: image-{assetId}-{width}x{height}-{format} const parts = imageRef.split('-'); if (parts.length < 2) { return imageRef; // Return as-is if not a valid Sanity reference } const assetId = parts[1]; const extension = parts[parts.length - 1] || 'jpg'; // Build Sanity CDN URL let url = `https://cdn.sanity.io/images/project/dataset/${assetId}.${extension}`; // Add transformations const params = new URLSearchParams(); if (options.width) { params.append('w', options.width.toString()); } if (options.height) { params.append('h', options.height.toString()); } if (options.fit) { params.append('fit', options.fit); } if (options.format && options.format !== 'auto') { params.append('fm', options.format); } if (options.quality) { params.append('q', options.quality.toString()); } const queryString = params.toString(); if (queryString) { url += `?${queryString}`; } return url; } /** * Get image MIME type from URL extension * * @param url - Image URL * @returns MIME type */ export function getImageTypeFromUrl(url) { const extension = url.split('.').pop()?.toLowerCase(); switch (extension) { case 'jpg': case 'jpeg': return 'image/jpeg'; case 'png': return 'image/png'; case 'webp': return 'image/webp'; case 'gif': return 'image/gif'; case 'svg': return 'image/svg+xml'; default: return 'image/jpeg'; } } /** * Generate optimized image dimensions for different use cases * * @param useCase - The intended use case for the image * @returns Optimal dimensions */ export function getOptimalImageDimensions(useCase) { switch (useCase) { case 'og': return { width: 1200, height: 630 }; case 'twitter': return { width: 1200, height: 628 }; case 'thumbnail': return { width: 400, height: 225 }; case 'hero': return { width: 1920, height: 1080 }; default: return { width: 1200, height: 630 }; } }