UNPKG

@dijitrak/react-nextjs-seo-plugin

Version:

A modern, user-friendly SEO plugin for React and Next.js with multilingual support and comprehensive optimization tools

222 lines (190 loc) 6.84 kB
/** * Meta etiketleri işlemleri */ import { SEOMetaData, LanguageMetadata } from '../types'; import type { Metadata } from 'next'; /** * Meta etiketleri oluşturur * @param metaData SEO meta verileri * @param baseUrl Temel site URL'si * @returns HTML meta etiketleri */ export function generateMetaTags(metaData: SEOMetaData, baseUrl: string = ''): string { // Boş meta verileri için varsayılan değerleri ekle const completeMeta: SEOMetaData = { title: '', description: '', keywords: '', allowIndex: true, allowFollow: true, canonicalUrl: '', ogTitle: '', ogDescription: '', ogImage: '', ogType: 'website', twitterTitle: '', twitterDescription: '', twitterImage: '', twitterCard: 'summary_large_image', language: 'en', // Özellikleri metaData'dan ekle, var olanları üzerine yaz ...metaData }; let tags = ''; // Temel meta etiketleri tags += `<title>${completeMeta.title}</title>\n`; tags += `<meta name="description" content="${completeMeta.description}" />\n`; if (completeMeta.keywords) { tags += `<meta name="keywords" content="${completeMeta.keywords}" />\n`; } // Dil if (completeMeta.language) { tags += `<meta http-equiv="content-language" content="${completeMeta.language}" />\n`; } // Robots meta etiketi const robotsValue = `${completeMeta.allowIndex ? 'index' : 'noindex'}, ${completeMeta.allowFollow ? 'follow' : 'nofollow'}`; tags += `<meta name="robots" content="${robotsValue}" />\n`; // Canonical link if (completeMeta.canonicalUrl) { let canonicalUrl = completeMeta.canonicalUrl; // Eğer başında http yoksa ve baseUrl verilmişse birleştir if (!canonicalUrl.startsWith('http') && baseUrl) { canonicalUrl = baseUrl.replace(/\/$/, '') + (canonicalUrl.startsWith('/') ? canonicalUrl : `/${canonicalUrl}`); } tags += `<link rel="canonical" href="${canonicalUrl}" />\n`; } // Open Graph meta etiketleri tags += `<meta property="og:title" content="${completeMeta.ogTitle || completeMeta.title}" />\n`; tags += `<meta property="og:description" content="${completeMeta.ogDescription || completeMeta.description}" />\n`; if (completeMeta.ogImage) { let ogImage = completeMeta.ogImage; // Eğer başında http yoksa ve baseUrl verilmişse birleştir if (!ogImage.startsWith('http') && baseUrl) { ogImage = baseUrl.replace(/\/$/, '') + (ogImage.startsWith('/') ? ogImage : `/${ogImage}`); } tags += `<meta property="og:image" content="${ogImage}" />\n`; } if (completeMeta.ogType) { tags += `<meta property="og:type" content="${completeMeta.ogType}" />\n`; } // Twitter Card meta etiketleri if (completeMeta.twitterCard) { tags += `<meta name="twitter:card" content="${completeMeta.twitterCard}" />\n`; } tags += `<meta name="twitter:title" content="${completeMeta.twitterTitle || completeMeta.ogTitle || completeMeta.title}" />\n`; tags += `<meta name="twitter:description" content="${completeMeta.twitterDescription || completeMeta.ogDescription || completeMeta.description}" />\n`; if (completeMeta.twitterImage || completeMeta.ogImage) { let twitterImage = completeMeta.twitterImage || completeMeta.ogImage; // Eğer başında http yoksa ve baseUrl verilmişse birleştir if (twitterImage && !twitterImage.startsWith('http') && baseUrl) { twitterImage = baseUrl.replace(/\/$/, '') + (twitterImage.startsWith('/') ? twitterImage : `/${twitterImage}`); } tags += `<meta name="twitter:image" content="${twitterImage}" />\n`; } // Site URL if (baseUrl) { tags += `<meta property="og:url" content="${baseUrl}" />\n`; } return tags; } /** * Hreflang etiketleri oluşturur * @param languageMetadata Dil metadata bilgileri * @param baseUrl Temel site URL'si * @returns HTML hreflang etiketleri */ export function generateHreflangTags(languageMetadata: LanguageMetadata, baseUrl: string = ''): string { if (!languageMetadata) return ''; let tags = ''; // Ana dil için hreflang etiketi if (languageMetadata.primary) { const href = baseUrl || '/'; tags += `<link rel="alternate" hreflang="${languageMetadata.primary}" href="${href}" />\n`; // x-default için hreflang etiketi (varsayılan dil) tags += `<link rel="alternate" hreflang="x-default" href="${href}" />\n`; } // Alternatif diller için hreflang etiketleri if (languageMetadata.alternate && languageMetadata.alternate.length > 0) { languageMetadata.alternate.forEach(alt => { tags += `<link rel="alternate" hreflang="${alt.hrefLang}" href="${alt.href}" />\n`; }); } return tags; } /** * Next.js App Router için Metadata nesnesini oluşturur * @param props Metadata nesne parametreleri * @returns Next.js Metadata nesnesi */ export function generateNextMetadata(props: { title?: string; description?: string; keywords?: string | string[]; openGraph?: { title?: string; description?: string; url?: string; siteName?: string; images?: Array<{ url: string; width?: number; height?: number; alt?: string; }>; type?: string; }; twitter?: { card?: 'summary' | 'summary_large_image' | 'app' | 'player'; title?: string; description?: string; creator?: string; images?: string[]; }; languageMetadata?: LanguageMetadata; }): Metadata { const { title, description, keywords, openGraph, twitter, languageMetadata } = props; const metadata: Metadata = { // title ve description özelliklerini koşullu olarak ekleyelim ...(title ? { title } : {}), ...(description ? { description } : {}), ...(keywords ? { keywords } : {}) }; // Open Graph metadata if (openGraph || title || description) { metadata.openGraph = { title: openGraph?.title || title || '', description: openGraph?.description || description || '', ...openGraph }; } // Twitter metadata if (twitter || title || description) { metadata.twitter = { title: twitter?.title || openGraph?.title || title || '', description: twitter?.description || openGraph?.description || description || '', card: twitter?.card || 'summary_large_image', ...twitter }; } // Alternatif dil bağlantıları if (languageMetadata && languageMetadata.alternate && languageMetadata.alternate.length > 0) { const alternates: Record<string, any> = { languages: {} }; if (languageMetadata.primary) { alternates.languages['x-default'] = '/'; } languageMetadata.alternate.forEach(alt => { alternates.languages[alt.hrefLang] = alt.href; }); metadata.alternates = alternates; } return metadata; }