canina/frontend/application/lib/schema.ts
parsaaghayi bd49fbc4a0
Some checks failed
Deploy Canina / deploy (push) Successful in 2m25s
E2E Playwright Tests / Run Full E2E & Security Suites (push) Failing after 7s
fix(security): remediate audit vulnerabilities SEC-001 through SEC-023
2026-09-23 23:00:25 +03:30

245 lines
7.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Structured Data (JSON-LD) Generators for Canina Iran
* Conforming to Schema.org and Google Search Rich Results guidelines
*/
export interface OrganizationSchemaOptions {
name?: string;
alternateName?: string;
url?: string;
logo?: string;
description?: string;
telephone?: string;
email?: string;
address?: {
streetAddress?: string;
addressLocality?: string;
addressRegion?: string;
postalCode?: string;
addressCountry?: string;
};
sameAs?: string[];
}
export function generateOrganizationSchema(options: OrganizationSchemaOptions = {}) {
const brandName = options.name || 'کنینا ایران';
const siteUrl = options.url || 'https://canina.ir';
const logoUrl = options.logo || `${siteUrl}/assets/images/logo.png`;
return {
'@context': 'https://schema.org',
'@type': 'Organization',
'@id': `${siteUrl}#organization`,
name: brandName,
alternateName: options.alternateName || 'Canina pharma GmbH Iran Representative',
url: siteUrl,
logo: {
'@type': 'ImageObject',
url: logoUrl,
caption: brandName,
},
image: logoUrl,
description:
options.description ||
'نماینده رسمی و انحصاری مکمل‌های دارویی و درمانی Canina pharma GmbH آلمان در ایران.',
telephone: options.telephone || '+989211231517',
email: options.email || 'caninairan@gmail.com',
address: {
'@type': 'PostalAddress',
streetAddress: options.address?.streetAddress || 'جردن، خیابان سعیدی، ساختمان کنینا، طبقه ۵',
addressLocality: options.address?.addressLocality || 'تهران',
addressRegion: options.address?.addressRegion || 'تهران',
postalCode: options.address?.postalCode || '1967812345',
addressCountry: options.address?.addressCountry || 'IR',
},
sameAs: options.sameAs || [
'https://instagram.com/caninairan',
'https://t.me/caninairan',
'https://www.canina.de',
],
contactPoint: [
{
'@type': 'ContactPoint',
telephone: options.telephone || '+989211231517',
contactType: 'customer service',
availableLanguage: ['Persian', 'English', 'German'],
areaServed: 'IR',
},
],
};
}
export function generateLocalBusinessSchema(options: OrganizationSchemaOptions = {}) {
const siteUrl = options.url || 'https://canina.ir';
const brandName = options.name || 'کنینا ایران';
const logoUrl = options.logo || `${siteUrl}/assets/images/logo.png`;
return {
'@context': 'https://schema.org',
'@type': 'VeterinaryCare',
'@id': `${siteUrl}#localbusiness`,
name: `${brandName} - دفتر مرکزی و پشتیبانی تخصصی`,
image: logoUrl,
url: siteUrl,
telephone: options.telephone || '+989211231517',
priceRange: '$$',
address: {
'@type': 'PostalAddress',
streetAddress: options.address?.streetAddress || 'تهران، جردن، خیابان سعیدی، ساختمان کنینا، طبقه ۵، واحد ۱۹',
addressLocality: options.address?.addressLocality || 'تهران',
addressRegion: options.address?.addressRegion || 'تهران',
postalCode: options.address?.postalCode || '1967812345',
addressCountry: 'IR',
},
geo: {
'@type': 'GeoCoordinates',
latitude: 35.7785,
longitude: 51.4172,
},
openingHoursSpecification: [
{
'@type': 'OpeningHoursSpecification',
dayOfWeek: ['Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday'],
opens: '09:00',
closes: '18:00',
},
],
sameAs: options.sameAs || [
'https://instagram.com/caninairan',
'https://t.me/caninairan',
],
};
}
export interface B2BServiceSchemaOptions {
serviceName?: string;
description?: string;
siteUrl?: string;
}
export function generateB2BServiceSchema(options: B2BServiceSchemaOptions = {}) {
const siteUrl = options.siteUrl || 'https://canina.ir';
return {
'@context': 'https://schema.org',
'@type': 'Service',
'@id': `${siteUrl}/b2b#service`,
name: options.serviceName || 'تأمین عمده و همکاری تجاری مکمل‌های دارویی کنینا آلمان',
serviceType: 'B2B Veterinary Supply & Wholesale',
provider: {
'@type': 'Organization',
name: 'کنینا ایران',
url: siteUrl,
logo: `${siteUrl}/assets/images/logo.png`,
},
areaServed: {
'@type': 'Country',
name: 'Iran',
},
description:
options.description ||
'تأمین مستقیم، پخش عمده و اعطای نمایندگی مکمل‌های تخصصی دامپزشکی Canina آلمان به کلینیک‌ها، بیمارستان‌های دامپزشکی و پت‌شاپ‌های معتبر سراسر کشور.',
offers: {
'@type': 'Offer',
availability: 'https://schema.org/InStock',
businessFunction: 'http://purl.org/goodrelations/v1#ProvideService',
},
};
}
export interface MedicalWebPageSchemaOptions {
title: string;
description: string;
url: string;
datePublished?: string;
dateModified?: string;
medicalAudience?: string;
aspects?: string[];
}
export function generateMedicalWebPageSchema(options: MedicalWebPageSchemaOptions) {
return {
'@context': 'https://schema.org',
'@type': 'MedicalWebPage',
name: options.title,
headline: options.title,
description: options.description,
url: options.url,
datePublished: options.datePublished || '2025-01-01',
dateModified: options.dateModified || new Date().toISOString(),
medicalAudience: {
'@type': 'MedicalAudience',
audienceType: options.medicalAudience || 'Veterinarians, Pet Care Professionals, and Pet Owners',
},
publisher: {
'@type': 'Organization',
name: 'کنینا ایران',
url: 'https://canina.ir',
},
about: options.aspects?.map((aspect) => ({
'@type': 'MedicalCondition',
name: aspect,
})) || [],
};
}
export interface VideoObjectSchemaOptions {
name: string;
description: string;
thumbnailUrl: string;
uploadDate: string;
contentUrl?: string;
embedUrl?: string;
duration?: string;
}
export function generateVideoObjectSchema(options: VideoObjectSchemaOptions) {
return {
'@context': 'https://schema.org',
'@type': 'VideoObject',
name: options.name,
description: options.description,
thumbnailUrl: [options.thumbnailUrl],
uploadDate: options.uploadDate,
contentUrl: options.contentUrl,
embedUrl: options.embedUrl || options.contentUrl,
duration: options.duration || 'PT3M30S',
publisher: {
'@type': 'Organization',
name: 'کنینا ایران',
logo: {
'@type': 'ImageObject',
url: 'https://canina.ir/assets/images/logo.png',
},
},
};
}
export interface BreadcrumbItem {
name: string;
url: string;
}
export function generateBreadcrumbSchema(items: BreadcrumbItem[]) {
return {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: items.map((item, index) => ({
'@type': 'ListItem',
position: index + 1,
name: item.name,
item: item.url,
})),
};
}
/**
* SEC-017: Safely serialize schema data to JSON string for application/ld+json script tags,
* escaping any '</script>' or '<' characters that could break out of the script block.
*/
export function safeJsonLd(schema: unknown): string {
return JSON.stringify(schema)
.replace(/</g, '\\u003c')
.replace(/>/g, '\\u003e')
.replace(/&/g, '\\u0026');
}