@power-seo/schema
Advanced tools
| /** Base type for all JSON-LD objects */ | ||
| interface JsonLdBase { | ||
| '@context'?: 'https://schema.org'; | ||
| '@type': string; | ||
| '@id'?: string; | ||
| } | ||
| /** A thing with a name and URL */ | ||
| interface ThingBase extends JsonLdBase { | ||
| name?: string; | ||
| url?: string; | ||
| description?: string; | ||
| image?: string | ImageObject | Array<string | ImageObject>; | ||
| sameAs?: string | string[]; | ||
| identifier?: string | { | ||
| '@type': 'PropertyValue'; | ||
| name: string; | ||
| value: string; | ||
| }; | ||
| alternateName?: string | string[]; | ||
| mainEntity?: JsonLdBase | JsonLdBase[]; | ||
| potentialAction?: JsonLdBase | JsonLdBase[]; | ||
| } | ||
| interface ImageObject extends JsonLdBase { | ||
| '@type': 'ImageObject'; | ||
| url: string; | ||
| width?: number | string; | ||
| height?: number | string; | ||
| caption?: string; | ||
| } | ||
| interface PersonSchema extends ThingBase { | ||
| '@type': 'Person'; | ||
| givenName?: string; | ||
| familyName?: string; | ||
| email?: string; | ||
| jobTitle?: string; | ||
| affiliation?: OrganizationSchema; | ||
| } | ||
| interface OrganizationSchema extends ThingBase { | ||
| '@type': 'Organization'; | ||
| logo?: string | ImageObject; | ||
| contactPoint?: ContactPoint | ContactPoint[]; | ||
| address?: PostalAddress; | ||
| foundingDate?: string; | ||
| numberOfEmployees?: number; | ||
| areaServed?: string | string[]; | ||
| foundingLocation?: PostalAddress | string; | ||
| knowsAbout?: string | string[]; | ||
| legalName?: string; | ||
| parentOrganization?: OrganizationSchema; | ||
| } | ||
| interface ContactPoint extends JsonLdBase { | ||
| '@type': 'ContactPoint'; | ||
| telephone?: string; | ||
| contactType?: string; | ||
| email?: string; | ||
| areaServed?: string | string[]; | ||
| availableLanguage?: string | string[]; | ||
| } | ||
| interface PostalAddress extends JsonLdBase { | ||
| '@type': 'PostalAddress'; | ||
| streetAddress?: string; | ||
| addressLocality?: string; | ||
| addressRegion?: string; | ||
| postalCode?: string; | ||
| addressCountry?: string; | ||
| } | ||
| interface ArticleSchema extends ThingBase { | ||
| '@type': 'Article' | 'BlogPosting' | 'NewsArticle' | 'TechArticle'; | ||
| headline: string; | ||
| author: PersonSchema | PersonSchema[] | OrganizationSchema | string; | ||
| datePublished: string; | ||
| dateModified?: string; | ||
| publisher?: OrganizationSchema; | ||
| mainEntityOfPage?: string | { | ||
| '@type': 'WebPage'; | ||
| '@id': string; | ||
| }; | ||
| articleBody?: string; | ||
| articleSection?: string; | ||
| wordCount?: number; | ||
| keywords?: string | string[]; | ||
| thumbnailUrl?: string; | ||
| } | ||
| interface ProductSchema extends ThingBase { | ||
| '@type': 'Product'; | ||
| brand?: OrganizationSchema | { | ||
| '@type': 'Brand'; | ||
| name: string; | ||
| }; | ||
| sku?: string; | ||
| gtin?: string; | ||
| gtin8?: string; | ||
| gtin13?: string; | ||
| gtin14?: string; | ||
| mpn?: string; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| review?: ReviewSchema | ReviewSchema[]; | ||
| color?: string; | ||
| material?: string; | ||
| } | ||
| interface OfferSchema extends JsonLdBase { | ||
| '@type': 'Offer' | 'AggregateOffer'; | ||
| price: number | string; | ||
| priceCurrency: string; | ||
| availability?: 'https://schema.org/InStock' | 'https://schema.org/OutOfStock' | 'https://schema.org/PreOrder' | 'https://schema.org/Discontinued' | string; | ||
| priceValidUntil?: string; | ||
| url?: string; | ||
| seller?: OrganizationSchema; | ||
| itemCondition?: string; | ||
| lowPrice?: number | string; | ||
| highPrice?: number | string; | ||
| offerCount?: number; | ||
| } | ||
| interface AggregateRatingSchema extends JsonLdBase { | ||
| '@type': 'AggregateRating'; | ||
| ratingValue: number | string; | ||
| reviewCount?: number; | ||
| ratingCount?: number; | ||
| bestRating?: number | string; | ||
| worstRating?: number | string; | ||
| } | ||
| interface ReviewSchema extends JsonLdBase { | ||
| '@type': 'Review'; | ||
| author: PersonSchema | string; | ||
| reviewRating?: RatingSchema; | ||
| reviewBody?: string; | ||
| datePublished?: string; | ||
| name?: string; | ||
| } | ||
| interface RatingSchema extends JsonLdBase { | ||
| '@type': 'Rating'; | ||
| ratingValue: number | string; | ||
| bestRating?: number | string; | ||
| worstRating?: number | string; | ||
| } | ||
| interface FAQPageSchema extends JsonLdBase { | ||
| '@type': 'FAQPage'; | ||
| mainEntity: FAQQuestionSchema[]; | ||
| } | ||
| interface FAQQuestionSchema extends JsonLdBase { | ||
| '@type': 'Question'; | ||
| name: string; | ||
| acceptedAnswer: { | ||
| '@type': 'Answer'; | ||
| text: string; | ||
| }; | ||
| } | ||
| interface BreadcrumbListSchema extends JsonLdBase { | ||
| '@type': 'BreadcrumbList'; | ||
| itemListElement: BreadcrumbItem[]; | ||
| } | ||
| interface BreadcrumbItem extends JsonLdBase { | ||
| '@type': 'ListItem'; | ||
| position: number; | ||
| name: string; | ||
| item?: string; | ||
| } | ||
| interface LocalBusinessSchema extends ThingBase { | ||
| '@type': 'LocalBusiness' | 'Restaurant' | 'Store' | 'MedicalBusiness' | string; | ||
| address: PostalAddress; | ||
| telephone?: string; | ||
| openingHoursSpecification?: OpeningHours | OpeningHours[]; | ||
| geo?: GeoCoordinates; | ||
| priceRange?: string; | ||
| servesCuisine?: string | string[]; | ||
| menu?: string; | ||
| hasMap?: string; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| review?: ReviewSchema | ReviewSchema[]; | ||
| } | ||
| interface OpeningHours extends JsonLdBase { | ||
| '@type': 'OpeningHoursSpecification'; | ||
| dayOfWeek: string | string[]; | ||
| opens: string; | ||
| closes: string; | ||
| } | ||
| interface GeoCoordinates extends JsonLdBase { | ||
| '@type': 'GeoCoordinates'; | ||
| latitude: number; | ||
| longitude: number; | ||
| } | ||
| interface EventSchema extends ThingBase { | ||
| '@type': 'Event' | 'MusicEvent' | 'BusinessEvent' | 'EducationEvent' | string; | ||
| startDate: string; | ||
| endDate?: string; | ||
| location: string | PostalAddress | { | ||
| '@type': 'VirtualLocation'; | ||
| url: string; | ||
| }; | ||
| organizer?: PersonSchema | OrganizationSchema; | ||
| performer?: PersonSchema | PersonSchema[]; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| eventStatus?: string; | ||
| eventAttendanceMode?: string; | ||
| } | ||
| interface RecipeSchema extends ThingBase { | ||
| '@type': 'Recipe'; | ||
| author: PersonSchema | string; | ||
| datePublished?: string; | ||
| prepTime?: string; | ||
| cookTime?: string; | ||
| totalTime?: string; | ||
| recipeYield?: string; | ||
| recipeCategory?: string; | ||
| recipeCuisine?: string; | ||
| recipeIngredient: string[]; | ||
| recipeInstructions: HowToStep[] | string[]; | ||
| nutrition?: NutritionInfo; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| video?: VideoObjectSchema; | ||
| keywords?: string; | ||
| } | ||
| interface NutritionInfo extends JsonLdBase { | ||
| '@type': 'NutritionInformation'; | ||
| calories?: string; | ||
| fatContent?: string; | ||
| carbohydrateContent?: string; | ||
| proteinContent?: string; | ||
| fiberContent?: string; | ||
| sodiumContent?: string; | ||
| sugarContent?: string; | ||
| } | ||
| interface HowToSchema extends ThingBase { | ||
| '@type': 'HowTo'; | ||
| step: HowToStep[]; | ||
| totalTime?: string; | ||
| estimatedCost?: string | MonetaryAmount; | ||
| supply?: HowToSupply[]; | ||
| tool?: HowToTool[]; | ||
| } | ||
| interface HowToStep extends JsonLdBase { | ||
| '@type': 'HowToStep'; | ||
| name?: string; | ||
| text: string; | ||
| url?: string; | ||
| image?: string; | ||
| } | ||
| interface HowToSupply extends JsonLdBase { | ||
| '@type': 'HowToSupply'; | ||
| name: string; | ||
| } | ||
| interface HowToTool extends JsonLdBase { | ||
| '@type': 'HowToTool'; | ||
| name: string; | ||
| } | ||
| interface MonetaryAmount extends JsonLdBase { | ||
| '@type': 'MonetaryAmount'; | ||
| currency: string; | ||
| value: number | string; | ||
| } | ||
| interface VideoObjectSchema extends ThingBase { | ||
| '@type': 'VideoObject'; | ||
| thumbnailUrl: string | string[]; | ||
| uploadDate: string; | ||
| duration?: string; | ||
| contentUrl?: string; | ||
| embedUrl?: string; | ||
| interactionStatistic?: { | ||
| '@type': 'InteractionCounter'; | ||
| interactionType: { | ||
| '@type': 'WatchAction'; | ||
| }; | ||
| userInteractionCount: number; | ||
| }; | ||
| } | ||
| interface CourseSchema extends ThingBase { | ||
| '@type': 'Course'; | ||
| provider?: OrganizationSchema; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| hasCourseInstance?: CourseInstance | CourseInstance[]; | ||
| coursePrerequisites?: string | string[]; | ||
| educationalLevel?: string; | ||
| } | ||
| interface CourseInstance extends JsonLdBase { | ||
| '@type': 'CourseInstance'; | ||
| courseMode?: string; | ||
| instructor?: PersonSchema; | ||
| startDate?: string; | ||
| endDate?: string; | ||
| } | ||
| interface JobPostingSchema extends ThingBase { | ||
| '@type': 'JobPosting'; | ||
| title: string; | ||
| datePosted: string; | ||
| validThrough?: string; | ||
| hiringOrganization: OrganizationSchema; | ||
| jobLocation?: PostalAddress | PostalAddress[]; | ||
| baseSalary?: MonetaryAmount | { | ||
| '@type': 'MonetaryAmount'; | ||
| currency: string; | ||
| value: { | ||
| '@type': 'QuantitativeValue'; | ||
| value?: number; | ||
| minValue?: number; | ||
| maxValue?: number; | ||
| unitText?: string; | ||
| }; | ||
| }; | ||
| employmentType?: string | string[]; | ||
| jobLocationType?: string; | ||
| applicantLocationRequirements?: { | ||
| '@type': 'Country'; | ||
| name: string; | ||
| } | Array<{ | ||
| '@type': 'Country'; | ||
| name: string; | ||
| }>; | ||
| } | ||
| interface SoftwareAppSchema extends ThingBase { | ||
| '@type': 'SoftwareApplication' | 'MobileApplication' | 'WebApplication'; | ||
| applicationCategory?: string; | ||
| operatingSystem?: string; | ||
| offers?: OfferSchema; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| downloadUrl?: string; | ||
| softwareVersion?: string; | ||
| } | ||
| interface BrandSchema extends JsonLdBase { | ||
| '@type': 'Brand'; | ||
| name: string; | ||
| logo?: string | ImageObject; | ||
| slogan?: string; | ||
| url?: string; | ||
| sameAs?: string | string[]; | ||
| } | ||
| interface SiteNavigationElementSchema extends ThingBase { | ||
| '@type': 'SiteNavigationElement'; | ||
| url: string; | ||
| } | ||
| interface WebSiteSchema extends ThingBase { | ||
| '@type': 'WebSite'; | ||
| potentialAction?: SearchActionSchema; | ||
| author?: PersonSchema | OrganizationSchema; | ||
| publisher?: OrganizationSchema; | ||
| mainEntity?: SiteNavigationElementSchema | SiteNavigationElementSchema[]; | ||
| inLanguage?: string; | ||
| dateCreated?: string; | ||
| dateModified?: string; | ||
| } | ||
| interface SearchActionSchema extends JsonLdBase { | ||
| '@type': 'SearchAction'; | ||
| target: string | { | ||
| '@type': 'EntryPoint'; | ||
| urlTemplate: string; | ||
| }; | ||
| 'query-input'?: string; | ||
| } | ||
| interface ItemListSchema extends JsonLdBase { | ||
| '@type': 'ItemList'; | ||
| itemListElement: ListItem[]; | ||
| numberOfItems?: number; | ||
| itemListOrder?: 'https://schema.org/ItemListOrderAscending' | 'https://schema.org/ItemListOrderDescending' | 'https://schema.org/ItemListUnordered' | string; | ||
| } | ||
| interface ListItem extends JsonLdBase { | ||
| '@type': 'ListItem'; | ||
| position: number; | ||
| url?: string; | ||
| name?: string; | ||
| item?: ThingBase; | ||
| } | ||
| interface ServiceSchema extends ThingBase { | ||
| '@type': 'Service'; | ||
| provider?: OrganizationSchema | PersonSchema; | ||
| areaServed?: string | string[]; | ||
| serviceType?: string; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| } | ||
| /** Union of all supported schema types */ | ||
| type SchemaObject = ArticleSchema | ProductSchema | FAQPageSchema | BreadcrumbListSchema | LocalBusinessSchema | OrganizationSchema | PersonSchema | EventSchema | RecipeSchema | HowToSchema | VideoObjectSchema | CourseSchema | JobPostingSchema | SoftwareAppSchema | WebSiteSchema | ItemListSchema | ReviewSchema | ServiceSchema | BrandSchema | SiteNavigationElementSchema; | ||
| /** JSON-LD with context */ | ||
| type WithContext<T extends JsonLdBase> = T & { | ||
| '@context': 'https://schema.org'; | ||
| }; | ||
| /** Schema graph — multiple connected schemas */ | ||
| interface SchemaGraph { | ||
| '@context': 'https://schema.org'; | ||
| '@graph': SchemaObject[]; | ||
| } | ||
| export type { ArticleSchema as A, BrandSchema as B, CourseSchema as C, EventSchema as E, FAQPageSchema as F, GeoCoordinates as G, HowToSchema as H, ImageObject as I, JobPostingSchema as J, LocalBusinessSchema as L, MonetaryAmount as M, NutritionInfo as N, OrganizationSchema as O, PersonSchema as P, RecipeSchema as R, SchemaObject as S, ThingBase as T, VideoObjectSchema as V, WithContext as W, BreadcrumbListSchema as a, ItemListSchema as b, ProductSchema as c, ReviewSchema as d, SchemaGraph as e, ServiceSchema as f, SiteNavigationElementSchema as g, SoftwareAppSchema as h, WebSiteSchema as i, AggregateRatingSchema as j, BreadcrumbItem as k, ContactPoint as l, CourseInstance as m, FAQQuestionSchema as n, HowToStep as o, HowToSupply as p, HowToTool as q, JsonLdBase as r, ListItem as s, OfferSchema as t, OpeningHours as u, PostalAddress as v, RatingSchema as w, SearchActionSchema as x }; |
| /** Base type for all JSON-LD objects */ | ||
| interface JsonLdBase { | ||
| '@context'?: 'https://schema.org'; | ||
| '@type': string; | ||
| '@id'?: string; | ||
| } | ||
| /** A thing with a name and URL */ | ||
| interface ThingBase extends JsonLdBase { | ||
| name?: string; | ||
| url?: string; | ||
| description?: string; | ||
| image?: string | ImageObject | Array<string | ImageObject>; | ||
| sameAs?: string | string[]; | ||
| identifier?: string | { | ||
| '@type': 'PropertyValue'; | ||
| name: string; | ||
| value: string; | ||
| }; | ||
| alternateName?: string | string[]; | ||
| mainEntity?: JsonLdBase | JsonLdBase[]; | ||
| potentialAction?: JsonLdBase | JsonLdBase[]; | ||
| } | ||
| interface ImageObject extends JsonLdBase { | ||
| '@type': 'ImageObject'; | ||
| url: string; | ||
| width?: number | string; | ||
| height?: number | string; | ||
| caption?: string; | ||
| } | ||
| interface PersonSchema extends ThingBase { | ||
| '@type': 'Person'; | ||
| givenName?: string; | ||
| familyName?: string; | ||
| email?: string; | ||
| jobTitle?: string; | ||
| affiliation?: OrganizationSchema; | ||
| } | ||
| interface OrganizationSchema extends ThingBase { | ||
| '@type': 'Organization'; | ||
| logo?: string | ImageObject; | ||
| contactPoint?: ContactPoint | ContactPoint[]; | ||
| address?: PostalAddress; | ||
| foundingDate?: string; | ||
| numberOfEmployees?: number; | ||
| areaServed?: string | string[]; | ||
| foundingLocation?: PostalAddress | string; | ||
| knowsAbout?: string | string[]; | ||
| legalName?: string; | ||
| parentOrganization?: OrganizationSchema; | ||
| } | ||
| interface ContactPoint extends JsonLdBase { | ||
| '@type': 'ContactPoint'; | ||
| telephone?: string; | ||
| contactType?: string; | ||
| email?: string; | ||
| areaServed?: string | string[]; | ||
| availableLanguage?: string | string[]; | ||
| } | ||
| interface PostalAddress extends JsonLdBase { | ||
| '@type': 'PostalAddress'; | ||
| streetAddress?: string; | ||
| addressLocality?: string; | ||
| addressRegion?: string; | ||
| postalCode?: string; | ||
| addressCountry?: string; | ||
| } | ||
| interface ArticleSchema extends ThingBase { | ||
| '@type': 'Article' | 'BlogPosting' | 'NewsArticle' | 'TechArticle'; | ||
| headline: string; | ||
| author: PersonSchema | PersonSchema[] | OrganizationSchema | string; | ||
| datePublished: string; | ||
| dateModified?: string; | ||
| publisher?: OrganizationSchema; | ||
| mainEntityOfPage?: string | { | ||
| '@type': 'WebPage'; | ||
| '@id': string; | ||
| }; | ||
| articleBody?: string; | ||
| articleSection?: string; | ||
| wordCount?: number; | ||
| keywords?: string | string[]; | ||
| thumbnailUrl?: string; | ||
| } | ||
| interface ProductSchema extends ThingBase { | ||
| '@type': 'Product'; | ||
| brand?: OrganizationSchema | { | ||
| '@type': 'Brand'; | ||
| name: string; | ||
| }; | ||
| sku?: string; | ||
| gtin?: string; | ||
| gtin8?: string; | ||
| gtin13?: string; | ||
| gtin14?: string; | ||
| mpn?: string; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| review?: ReviewSchema | ReviewSchema[]; | ||
| color?: string; | ||
| material?: string; | ||
| } | ||
| interface OfferSchema extends JsonLdBase { | ||
| '@type': 'Offer' | 'AggregateOffer'; | ||
| price: number | string; | ||
| priceCurrency: string; | ||
| availability?: 'https://schema.org/InStock' | 'https://schema.org/OutOfStock' | 'https://schema.org/PreOrder' | 'https://schema.org/Discontinued' | string; | ||
| priceValidUntil?: string; | ||
| url?: string; | ||
| seller?: OrganizationSchema; | ||
| itemCondition?: string; | ||
| lowPrice?: number | string; | ||
| highPrice?: number | string; | ||
| offerCount?: number; | ||
| } | ||
| interface AggregateRatingSchema extends JsonLdBase { | ||
| '@type': 'AggregateRating'; | ||
| ratingValue: number | string; | ||
| reviewCount?: number; | ||
| ratingCount?: number; | ||
| bestRating?: number | string; | ||
| worstRating?: number | string; | ||
| } | ||
| interface ReviewSchema extends JsonLdBase { | ||
| '@type': 'Review'; | ||
| author: PersonSchema | string; | ||
| reviewRating?: RatingSchema; | ||
| reviewBody?: string; | ||
| datePublished?: string; | ||
| name?: string; | ||
| } | ||
| interface RatingSchema extends JsonLdBase { | ||
| '@type': 'Rating'; | ||
| ratingValue: number | string; | ||
| bestRating?: number | string; | ||
| worstRating?: number | string; | ||
| } | ||
| interface FAQPageSchema extends JsonLdBase { | ||
| '@type': 'FAQPage'; | ||
| mainEntity: FAQQuestionSchema[]; | ||
| } | ||
| interface FAQQuestionSchema extends JsonLdBase { | ||
| '@type': 'Question'; | ||
| name: string; | ||
| acceptedAnswer: { | ||
| '@type': 'Answer'; | ||
| text: string; | ||
| }; | ||
| } | ||
| interface BreadcrumbListSchema extends JsonLdBase { | ||
| '@type': 'BreadcrumbList'; | ||
| itemListElement: BreadcrumbItem[]; | ||
| } | ||
| interface BreadcrumbItem extends JsonLdBase { | ||
| '@type': 'ListItem'; | ||
| position: number; | ||
| name: string; | ||
| item?: string; | ||
| } | ||
| interface LocalBusinessSchema extends ThingBase { | ||
| '@type': 'LocalBusiness' | 'Restaurant' | 'Store' | 'MedicalBusiness' | string; | ||
| address: PostalAddress; | ||
| telephone?: string; | ||
| openingHoursSpecification?: OpeningHours | OpeningHours[]; | ||
| geo?: GeoCoordinates; | ||
| priceRange?: string; | ||
| servesCuisine?: string | string[]; | ||
| menu?: string; | ||
| hasMap?: string; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| review?: ReviewSchema | ReviewSchema[]; | ||
| } | ||
| interface OpeningHours extends JsonLdBase { | ||
| '@type': 'OpeningHoursSpecification'; | ||
| dayOfWeek: string | string[]; | ||
| opens: string; | ||
| closes: string; | ||
| } | ||
| interface GeoCoordinates extends JsonLdBase { | ||
| '@type': 'GeoCoordinates'; | ||
| latitude: number; | ||
| longitude: number; | ||
| } | ||
| interface EventSchema extends ThingBase { | ||
| '@type': 'Event' | 'MusicEvent' | 'BusinessEvent' | 'EducationEvent' | string; | ||
| startDate: string; | ||
| endDate?: string; | ||
| location: string | PostalAddress | { | ||
| '@type': 'VirtualLocation'; | ||
| url: string; | ||
| }; | ||
| organizer?: PersonSchema | OrganizationSchema; | ||
| performer?: PersonSchema | PersonSchema[]; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| eventStatus?: string; | ||
| eventAttendanceMode?: string; | ||
| } | ||
| interface RecipeSchema extends ThingBase { | ||
| '@type': 'Recipe'; | ||
| author: PersonSchema | string; | ||
| datePublished?: string; | ||
| prepTime?: string; | ||
| cookTime?: string; | ||
| totalTime?: string; | ||
| recipeYield?: string; | ||
| recipeCategory?: string; | ||
| recipeCuisine?: string; | ||
| recipeIngredient: string[]; | ||
| recipeInstructions: HowToStep[] | string[]; | ||
| nutrition?: NutritionInfo; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| video?: VideoObjectSchema; | ||
| keywords?: string; | ||
| } | ||
| interface NutritionInfo extends JsonLdBase { | ||
| '@type': 'NutritionInformation'; | ||
| calories?: string; | ||
| fatContent?: string; | ||
| carbohydrateContent?: string; | ||
| proteinContent?: string; | ||
| fiberContent?: string; | ||
| sodiumContent?: string; | ||
| sugarContent?: string; | ||
| } | ||
| interface HowToSchema extends ThingBase { | ||
| '@type': 'HowTo'; | ||
| step: HowToStep[]; | ||
| totalTime?: string; | ||
| estimatedCost?: string | MonetaryAmount; | ||
| supply?: HowToSupply[]; | ||
| tool?: HowToTool[]; | ||
| } | ||
| interface HowToStep extends JsonLdBase { | ||
| '@type': 'HowToStep'; | ||
| name?: string; | ||
| text: string; | ||
| url?: string; | ||
| image?: string; | ||
| } | ||
| interface HowToSupply extends JsonLdBase { | ||
| '@type': 'HowToSupply'; | ||
| name: string; | ||
| } | ||
| interface HowToTool extends JsonLdBase { | ||
| '@type': 'HowToTool'; | ||
| name: string; | ||
| } | ||
| interface MonetaryAmount extends JsonLdBase { | ||
| '@type': 'MonetaryAmount'; | ||
| currency: string; | ||
| value: number | string; | ||
| } | ||
| interface VideoObjectSchema extends ThingBase { | ||
| '@type': 'VideoObject'; | ||
| thumbnailUrl: string | string[]; | ||
| uploadDate: string; | ||
| duration?: string; | ||
| contentUrl?: string; | ||
| embedUrl?: string; | ||
| interactionStatistic?: { | ||
| '@type': 'InteractionCounter'; | ||
| interactionType: { | ||
| '@type': 'WatchAction'; | ||
| }; | ||
| userInteractionCount: number; | ||
| }; | ||
| } | ||
| interface CourseSchema extends ThingBase { | ||
| '@type': 'Course'; | ||
| provider?: OrganizationSchema; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| hasCourseInstance?: CourseInstance | CourseInstance[]; | ||
| coursePrerequisites?: string | string[]; | ||
| educationalLevel?: string; | ||
| } | ||
| interface CourseInstance extends JsonLdBase { | ||
| '@type': 'CourseInstance'; | ||
| courseMode?: string; | ||
| instructor?: PersonSchema; | ||
| startDate?: string; | ||
| endDate?: string; | ||
| } | ||
| interface JobPostingSchema extends ThingBase { | ||
| '@type': 'JobPosting'; | ||
| title: string; | ||
| datePosted: string; | ||
| validThrough?: string; | ||
| hiringOrganization: OrganizationSchema; | ||
| jobLocation?: PostalAddress | PostalAddress[]; | ||
| baseSalary?: MonetaryAmount | { | ||
| '@type': 'MonetaryAmount'; | ||
| currency: string; | ||
| value: { | ||
| '@type': 'QuantitativeValue'; | ||
| value?: number; | ||
| minValue?: number; | ||
| maxValue?: number; | ||
| unitText?: string; | ||
| }; | ||
| }; | ||
| employmentType?: string | string[]; | ||
| jobLocationType?: string; | ||
| applicantLocationRequirements?: { | ||
| '@type': 'Country'; | ||
| name: string; | ||
| } | Array<{ | ||
| '@type': 'Country'; | ||
| name: string; | ||
| }>; | ||
| } | ||
| interface SoftwareAppSchema extends ThingBase { | ||
| '@type': 'SoftwareApplication' | 'MobileApplication' | 'WebApplication'; | ||
| applicationCategory?: string; | ||
| operatingSystem?: string; | ||
| offers?: OfferSchema; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| downloadUrl?: string; | ||
| softwareVersion?: string; | ||
| } | ||
| interface BrandSchema extends JsonLdBase { | ||
| '@type': 'Brand'; | ||
| name: string; | ||
| logo?: string | ImageObject; | ||
| slogan?: string; | ||
| url?: string; | ||
| sameAs?: string | string[]; | ||
| } | ||
| interface SiteNavigationElementSchema extends ThingBase { | ||
| '@type': 'SiteNavigationElement'; | ||
| url: string; | ||
| } | ||
| interface WebSiteSchema extends ThingBase { | ||
| '@type': 'WebSite'; | ||
| potentialAction?: SearchActionSchema; | ||
| author?: PersonSchema | OrganizationSchema; | ||
| publisher?: OrganizationSchema; | ||
| mainEntity?: SiteNavigationElementSchema | SiteNavigationElementSchema[]; | ||
| inLanguage?: string; | ||
| dateCreated?: string; | ||
| dateModified?: string; | ||
| } | ||
| interface SearchActionSchema extends JsonLdBase { | ||
| '@type': 'SearchAction'; | ||
| target: string | { | ||
| '@type': 'EntryPoint'; | ||
| urlTemplate: string; | ||
| }; | ||
| 'query-input'?: string; | ||
| } | ||
| interface ItemListSchema extends JsonLdBase { | ||
| '@type': 'ItemList'; | ||
| itemListElement: ListItem[]; | ||
| numberOfItems?: number; | ||
| itemListOrder?: 'https://schema.org/ItemListOrderAscending' | 'https://schema.org/ItemListOrderDescending' | 'https://schema.org/ItemListUnordered' | string; | ||
| } | ||
| interface ListItem extends JsonLdBase { | ||
| '@type': 'ListItem'; | ||
| position: number; | ||
| url?: string; | ||
| name?: string; | ||
| item?: ThingBase; | ||
| } | ||
| interface ServiceSchema extends ThingBase { | ||
| '@type': 'Service'; | ||
| provider?: OrganizationSchema | PersonSchema; | ||
| areaServed?: string | string[]; | ||
| serviceType?: string; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| } | ||
| /** Union of all supported schema types */ | ||
| type SchemaObject = ArticleSchema | ProductSchema | FAQPageSchema | BreadcrumbListSchema | LocalBusinessSchema | OrganizationSchema | PersonSchema | EventSchema | RecipeSchema | HowToSchema | VideoObjectSchema | CourseSchema | JobPostingSchema | SoftwareAppSchema | WebSiteSchema | ItemListSchema | ReviewSchema | ServiceSchema | BrandSchema | SiteNavigationElementSchema; | ||
| /** JSON-LD with context */ | ||
| type WithContext<T extends JsonLdBase> = T & { | ||
| '@context': 'https://schema.org'; | ||
| }; | ||
| /** Schema graph — multiple connected schemas */ | ||
| interface SchemaGraph { | ||
| '@context': 'https://schema.org'; | ||
| '@graph': SchemaObject[]; | ||
| } | ||
| export type { ArticleSchema as A, BrandSchema as B, CourseSchema as C, EventSchema as E, FAQPageSchema as F, GeoCoordinates as G, HowToSchema as H, ImageObject as I, JobPostingSchema as J, LocalBusinessSchema as L, MonetaryAmount as M, NutritionInfo as N, OrganizationSchema as O, PersonSchema as P, RecipeSchema as R, SchemaObject as S, ThingBase as T, VideoObjectSchema as V, WithContext as W, BreadcrumbListSchema as a, ItemListSchema as b, ProductSchema as c, ReviewSchema as d, SchemaGraph as e, ServiceSchema as f, SiteNavigationElementSchema as g, SoftwareAppSchema as h, WebSiteSchema as i, AggregateRatingSchema as j, BreadcrumbItem as k, ContactPoint as l, CourseInstance as m, FAQQuestionSchema as n, HowToStep as o, HowToSupply as p, HowToTool as q, JsonLdBase as r, ListItem as s, OfferSchema as t, OpeningHours as u, PostalAddress as v, RatingSchema as w, SearchActionSchema as x }; |
+102
-27
@@ -1,3 +0,52 @@ | ||
| 'use strict'; | ||
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| // src/index.ts | ||
| var src_exports = {}; | ||
| __export(src_exports, { | ||
| article: () => article, | ||
| blogPosting: () => blogPosting, | ||
| brand: () => brand, | ||
| breadcrumbList: () => breadcrumbList, | ||
| course: () => course, | ||
| event: () => event, | ||
| faqPage: () => faqPage, | ||
| howTo: () => howTo, | ||
| imageObject: () => imageObject, | ||
| itemList: () => itemList, | ||
| jobPosting: () => jobPosting, | ||
| localBusiness: () => localBusiness, | ||
| newsArticle: () => newsArticle, | ||
| organization: () => organization, | ||
| person: () => person, | ||
| product: () => product, | ||
| recipe: () => recipe, | ||
| review: () => review, | ||
| schemaGraph: () => schemaGraph, | ||
| service: () => service, | ||
| siteNavigationElement: () => siteNavigationElement, | ||
| softwareApp: () => softwareApp, | ||
| toJsonLdString: () => toJsonLdString, | ||
| validateSchema: () => validateSchema, | ||
| videoObject: () => videoObject, | ||
| webSite: () => webSite | ||
| }); | ||
| module.exports = __toCommonJS(src_exports); | ||
| // src/builders.ts | ||
@@ -99,2 +148,13 @@ var CONTEXT = "https://schema.org"; | ||
| } | ||
| function brand(props) { | ||
| return withContext(clean({ "@type": "Brand", ...props })); | ||
| } | ||
| function siteNavigationElement(props) { | ||
| return withContext( | ||
| clean({ "@type": "SiteNavigationElement", ...props }) | ||
| ); | ||
| } | ||
| function imageObject(props) { | ||
| return withContext(clean({ "@type": "ImageObject", ...props })); | ||
| } | ||
| function schemaGraph(schemas) { | ||
@@ -107,3 +167,3 @@ return { | ||
| function toJsonLdString(schema, pretty = false) { | ||
| return JSON.stringify(schema, null, pretty ? 2 : void 0); | ||
| return JSON.stringify(schema, null, pretty ? 2 : void 0).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026"); | ||
| } | ||
@@ -113,2 +173,13 @@ | ||
| function validateSchema(schema) { | ||
| if (Array.isArray(schema)) { | ||
| const allIssues = []; | ||
| for (const s of schema) { | ||
| const result = validateSchema(s); | ||
| allIssues.push(...result.issues); | ||
| } | ||
| return { | ||
| valid: allIssues.filter((i) => i.severity === "error").length === 0, | ||
| issues: allIssues | ||
| }; | ||
| } | ||
| const issues = []; | ||
@@ -295,27 +366,31 @@ const obj = schema; | ||
| } | ||
| exports.article = article; | ||
| exports.blogPosting = blogPosting; | ||
| exports.breadcrumbList = breadcrumbList; | ||
| exports.course = course; | ||
| exports.event = event; | ||
| exports.faqPage = faqPage; | ||
| exports.howTo = howTo; | ||
| exports.itemList = itemList; | ||
| exports.jobPosting = jobPosting; | ||
| exports.localBusiness = localBusiness; | ||
| exports.newsArticle = newsArticle; | ||
| exports.organization = organization; | ||
| exports.person = person; | ||
| exports.product = product; | ||
| exports.recipe = recipe; | ||
| exports.review = review; | ||
| exports.schemaGraph = schemaGraph; | ||
| exports.service = service; | ||
| exports.softwareApp = softwareApp; | ||
| exports.toJsonLdString = toJsonLdString; | ||
| exports.validateSchema = validateSchema; | ||
| exports.videoObject = videoObject; | ||
| exports.webSite = webSite; | ||
| //# sourceMappingURL=index.cjs.map | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| article, | ||
| blogPosting, | ||
| brand, | ||
| breadcrumbList, | ||
| course, | ||
| event, | ||
| faqPage, | ||
| howTo, | ||
| imageObject, | ||
| itemList, | ||
| jobPosting, | ||
| localBusiness, | ||
| newsArticle, | ||
| organization, | ||
| person, | ||
| product, | ||
| recipe, | ||
| review, | ||
| schemaGraph, | ||
| service, | ||
| siteNavigationElement, | ||
| softwareApp, | ||
| toJsonLdString, | ||
| validateSchema, | ||
| videoObject, | ||
| webSite | ||
| }); | ||
| //# sourceMappingURL=index.cjs.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/builders.ts","../src/validation.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["// ============================================================================\n// @power-seo/schema — JSON-LD Builder Functions\n// ============================================================================\n\nimport type {\n WithContext,\n ArticleSchema,\n ProductSchema,\n FAQPageSchema,\n FAQQuestionSchema,\n BreadcrumbListSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n PersonSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ItemListSchema,\n ReviewSchema,\n ServiceSchema,\n SchemaGraph,\n SchemaObject,\n} from './types.js';\n\nconst CONTEXT = 'https://schema.org' as const;\n\n/** Add @context to a schema object */\nfunction withContext<T extends { '@type': string }>(\n schema: T,\n): WithContext<T & { '@type': string }> {\n return { '@context': CONTEXT, ...schema };\n}\n\n/** Remove undefined values from an object */\nfunction clean<T extends Record<string, unknown>>(obj: T): T {\n const result = {} as Record<string, unknown>;\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result as T;\n}\n\n// --- Builder Functions ---\n\nexport function article(\n props: Omit<ArticleSchema, '@type'> & { type?: ArticleSchema['@type'] },\n): WithContext<ArticleSchema> {\n const { type = 'Article', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as ArticleSchema);\n}\n\nexport function blogPosting(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'BlogPosting' });\n}\n\nexport function newsArticle(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'NewsArticle' });\n}\n\nexport function product(props: Omit<ProductSchema, '@type'>): WithContext<ProductSchema> {\n return withContext(clean({ '@type': 'Product', ...props }) as ProductSchema);\n}\n\nexport function faqPage(\n questions: Array<{ question: string; answer: string }>,\n): WithContext<FAQPageSchema> {\n const mainEntity: FAQQuestionSchema[] = questions.map((q) => ({\n '@type': 'Question' as const,\n name: q.question,\n acceptedAnswer: {\n '@type': 'Answer' as const,\n text: q.answer,\n },\n }));\n\n return withContext({ '@type': 'FAQPage' as const, mainEntity });\n}\n\nexport function breadcrumbList(\n items: Array<{ name: string; url?: string }>,\n): WithContext<BreadcrumbListSchema> {\n return withContext({\n '@type': 'BreadcrumbList' as const,\n itemListElement: items.map((item, index) =>\n clean({\n '@type': 'ListItem' as const,\n position: index + 1,\n name: item.name,\n item: item.url,\n }),\n ),\n });\n}\n\nexport function localBusiness(\n props: Omit<LocalBusinessSchema, '@type'> & { type?: string },\n): WithContext<LocalBusinessSchema> {\n const { type = 'LocalBusiness', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as LocalBusinessSchema);\n}\n\nexport function organization(\n props: Omit<OrganizationSchema, '@type'>,\n): WithContext<OrganizationSchema> {\n return withContext(clean({ '@type': 'Organization', ...props }) as OrganizationSchema);\n}\n\nexport function person(props: Omit<PersonSchema, '@type'>): WithContext<PersonSchema> {\n return withContext(clean({ '@type': 'Person', ...props }) as PersonSchema);\n}\n\nexport function event(\n props: Omit<EventSchema, '@type'> & { type?: EventSchema['@type'] },\n): WithContext<EventSchema> {\n const { type = 'Event', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as EventSchema);\n}\n\nexport function recipe(props: Omit<RecipeSchema, '@type'>): WithContext<RecipeSchema> {\n return withContext(clean({ '@type': 'Recipe', ...props }) as RecipeSchema);\n}\n\nexport function howTo(props: Omit<HowToSchema, '@type'>): WithContext<HowToSchema> {\n return withContext(clean({ '@type': 'HowTo', ...props }) as HowToSchema);\n}\n\nexport function videoObject(\n props: Omit<VideoObjectSchema, '@type'>,\n): WithContext<VideoObjectSchema> {\n return withContext(clean({ '@type': 'VideoObject', ...props }) as VideoObjectSchema);\n}\n\nexport function course(props: Omit<CourseSchema, '@type'>): WithContext<CourseSchema> {\n return withContext(clean({ '@type': 'Course', ...props }) as CourseSchema);\n}\n\nexport function jobPosting(props: Omit<JobPostingSchema, '@type'>): WithContext<JobPostingSchema> {\n return withContext(clean({ '@type': 'JobPosting', ...props }) as JobPostingSchema);\n}\n\nexport function softwareApp(\n props: Omit<SoftwareAppSchema, '@type'> & { type?: SoftwareAppSchema['@type'] },\n): WithContext<SoftwareAppSchema> {\n const { type = 'SoftwareApplication', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as SoftwareAppSchema);\n}\n\nexport function webSite(props: Omit<WebSiteSchema, '@type'>): WithContext<WebSiteSchema> {\n return withContext(clean({ '@type': 'WebSite', ...props }) as WebSiteSchema);\n}\n\nexport function itemList(props: Omit<ItemListSchema, '@type'>): WithContext<ItemListSchema> {\n return withContext(clean({ '@type': 'ItemList', ...props }) as ItemListSchema);\n}\n\nexport function review(props: Omit<ReviewSchema, '@type'>): WithContext<ReviewSchema> {\n return withContext(clean({ '@type': 'Review', ...props }) as ReviewSchema);\n}\n\nexport function service(props: Omit<ServiceSchema, '@type'>): WithContext<ServiceSchema> {\n return withContext(clean({ '@type': 'Service', ...props }) as ServiceSchema);\n}\n\n// --- Schema Graph Builder ---\n\n/**\n * Build a connected schema graph with multiple types.\n *\n * @example\n * ```ts\n * const graph = schemaGraph([\n * { '@type': 'WebSite', name: 'My Site', url: 'https://example.com' },\n * { '@type': 'Organization', name: 'My Org', url: 'https://example.com' },\n * ]);\n * ```\n */\nexport function schemaGraph(schemas: SchemaObject[]): SchemaGraph {\n return {\n '@context': CONTEXT,\n '@graph': schemas,\n };\n}\n\n/**\n * Serialize a schema object to a JSON-LD string.\n */\nexport function toJsonLdString(\n schema: WithContext<SchemaObject> | SchemaGraph,\n pretty = false,\n): string {\n return JSON.stringify(schema, null, pretty ? 2 : undefined);\n}\n","// ============================================================================\n// @power-seo/schema — Google Rich Results Validation\n// ============================================================================\n\nimport type { SchemaObject } from './types.js';\n\nexport interface ValidationIssue {\n severity: 'error' | 'warning';\n field: string;\n message: string;\n}\n\nexport interface SchemaValidationResult {\n valid: boolean;\n issues: ValidationIssue[];\n}\n\n/**\n * Validate a schema object against Google Rich Results requirements.\n * This checks required fields beyond basic Schema.org conformance.\n */\nexport function validateSchema(schema: SchemaObject): SchemaValidationResult {\n const issues: ValidationIssue[] = [];\n\n const obj = schema as unknown as Record<string, unknown>;\n\n switch (schema['@type']) {\n case 'Article':\n case 'BlogPosting':\n case 'NewsArticle':\n case 'TechArticle':\n validateArticle(obj, issues);\n break;\n case 'Product':\n validateProduct(obj, issues);\n break;\n case 'FAQPage':\n validateFAQPage(obj, issues);\n break;\n case 'BreadcrumbList':\n validateBreadcrumbList(obj, issues);\n break;\n case 'Event':\n case 'MusicEvent':\n case 'BusinessEvent':\n case 'EducationEvent':\n validateEvent(obj, issues);\n break;\n case 'Recipe':\n validateRecipe(obj, issues);\n break;\n case 'VideoObject':\n validateVideoObject(obj, issues);\n break;\n case 'JobPosting':\n validateJobPosting(obj, issues);\n break;\n case 'LocalBusiness':\n case 'Restaurant':\n case 'Store':\n validateLocalBusiness(obj, issues);\n break;\n case 'Course':\n validateCourse(obj, issues);\n break;\n }\n\n return {\n valid: issues.filter((i) => i.severity === 'error').length === 0,\n issues,\n };\n}\n\nfunction requireField(obj: Record<string, unknown>, field: string, issues: ValidationIssue[]) {\n if (obj[field] === undefined || obj[field] === null || obj[field] === '') {\n issues.push({\n severity: 'error',\n field,\n message: `Required field \"${field}\" is missing.`,\n });\n }\n}\n\nfunction recommendField(obj: Record<string, unknown>, field: string, issues: ValidationIssue[]) {\n if (obj[field] === undefined || obj[field] === null || obj[field] === '') {\n issues.push({\n severity: 'warning',\n field,\n message: `Recommended field \"${field}\" is missing.`,\n });\n }\n}\n\nfunction validateArticle(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'headline', issues);\n requireField(schema, 'author', issues);\n requireField(schema, 'datePublished', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'dateModified', issues);\n recommendField(schema, 'publisher', issues);\n recommendField(schema, 'mainEntityOfPage', issues);\n\n if (typeof schema.headline === 'string' && schema.headline.length > 110) {\n issues.push({\n severity: 'warning',\n field: 'headline',\n message: 'Headline should be under 110 characters for Google Rich Results.',\n });\n }\n}\n\nfunction validateProduct(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'offers', issues);\n recommendField(schema, 'aggregateRating', issues);\n recommendField(schema, 'brand', issues);\n recommendField(schema, 'sku', issues);\n}\n\nfunction validateFAQPage(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n const mainEntity = schema.mainEntity as Array<Record<string, unknown>> | undefined;\n if (!mainEntity || !Array.isArray(mainEntity) || mainEntity.length === 0) {\n issues.push({\n severity: 'error',\n field: 'mainEntity',\n message: 'FAQPage requires at least one Question in mainEntity.',\n });\n return;\n }\n\n for (let i = 0; i < mainEntity.length; i++) {\n const q = mainEntity[i]!;\n if (!q.name) {\n issues.push({\n severity: 'error',\n field: `mainEntity[${i}].name`,\n message: `Question ${i + 1} is missing \"name\" (the question text).`,\n });\n }\n const answer = q.acceptedAnswer as Record<string, unknown> | undefined;\n if (!answer?.text) {\n issues.push({\n severity: 'error',\n field: `mainEntity[${i}].acceptedAnswer.text`,\n message: `Question ${i + 1} is missing an answer text.`,\n });\n }\n }\n}\n\nfunction validateBreadcrumbList(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n const items = schema.itemListElement as Array<Record<string, unknown>> | undefined;\n if (!items || !Array.isArray(items) || items.length === 0) {\n issues.push({\n severity: 'error',\n field: 'itemListElement',\n message: 'BreadcrumbList requires at least one ListItem.',\n });\n }\n}\n\nfunction validateEvent(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'startDate', issues);\n requireField(schema, 'location', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'offers', issues);\n recommendField(schema, 'organizer', issues);\n}\n\nfunction validateRecipe(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'image', issues);\n requireField(schema, 'recipeIngredient', issues);\n requireField(schema, 'recipeInstructions', issues);\n recommendField(schema, 'author', issues);\n recommendField(schema, 'datePublished', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'prepTime', issues);\n recommendField(schema, 'totalTime', issues);\n}\n\nfunction validateVideoObject(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'description', issues);\n requireField(schema, 'thumbnailUrl', issues);\n requireField(schema, 'uploadDate', issues);\n recommendField(schema, 'contentUrl', issues);\n recommendField(schema, 'duration', issues);\n}\n\nfunction validateJobPosting(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'title', issues);\n requireField(schema, 'description', issues);\n requireField(schema, 'datePosted', issues);\n requireField(schema, 'hiringOrganization', issues);\n recommendField(schema, 'validThrough', issues);\n recommendField(schema, 'employmentType', issues);\n recommendField(schema, 'baseSalary', issues);\n}\n\nfunction validateLocalBusiness(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'address', issues);\n recommendField(schema, 'telephone', issues);\n recommendField(schema, 'openingHoursSpecification', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'url', issues);\n recommendField(schema, 'geo', issues);\n}\n\nfunction validateCourse(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'description', issues);\n recommendField(schema, 'provider', issues);\n recommendField(schema, 'offers', issues);\n}\n"]} | ||
| {"version":3,"sources":["../src/index.ts","../src/builders.ts","../src/validation.ts"],"sourcesContent":["// @power-seo/schema — Main Entry Point (framework-agnostic)\n// ----------------------------------------------------------------------------\n\n// Types\nexport type {\n JsonLdBase,\n ThingBase,\n ImageObject,\n PersonSchema,\n OrganizationSchema,\n ContactPoint,\n PostalAddress,\n ArticleSchema,\n ProductSchema,\n OfferSchema,\n AggregateRatingSchema,\n ReviewSchema,\n RatingSchema,\n FAQPageSchema,\n FAQQuestionSchema,\n BreadcrumbListSchema,\n BreadcrumbItem,\n LocalBusinessSchema,\n OpeningHours,\n GeoCoordinates,\n EventSchema,\n RecipeSchema,\n NutritionInfo,\n HowToSchema,\n HowToStep,\n HowToSupply,\n HowToTool,\n MonetaryAmount,\n VideoObjectSchema,\n CourseSchema,\n CourseInstance,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n SearchActionSchema,\n ItemListSchema,\n ListItem,\n ServiceSchema,\n BrandSchema,\n SiteNavigationElementSchema,\n SchemaObject,\n WithContext,\n SchemaGraph,\n} from './types.js';\n\n// Builder Functions\nexport {\n article,\n blogPosting,\n newsArticle,\n product,\n faqPage,\n breadcrumbList,\n localBusiness,\n organization,\n person,\n event,\n recipe,\n howTo,\n videoObject,\n course,\n jobPosting,\n softwareApp,\n webSite,\n itemList,\n review,\n service,\n brand,\n siteNavigationElement,\n imageObject,\n schemaGraph,\n toJsonLdString,\n} from './builders.js';\n\n// Validation\nexport { validateSchema } from './validation.js';\nexport type { ValidationIssue, SchemaValidationResult } from './validation.js';\n","// @power-seo/schema — JSON-LD Builder Functions\n// ----------------------------------------------------------------------------\n\nimport type {\n WithContext,\n ArticleSchema,\n ProductSchema,\n FAQPageSchema,\n FAQQuestionSchema,\n BreadcrumbListSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n PersonSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ItemListSchema,\n ReviewSchema,\n ServiceSchema,\n BrandSchema,\n SiteNavigationElementSchema,\n ImageObject,\n SchemaGraph,\n SchemaObject,\n} from './types.js';\n\nconst CONTEXT = 'https://schema.org' as const;\n\n/** Add @context to a schema object */\nfunction withContext<T extends { '@type': string }>(\n schema: T,\n): WithContext<T & { '@type': string }> {\n return { '@context': CONTEXT, ...schema };\n}\n\n/** Remove undefined values from an object */\nfunction clean<T extends Record<string, unknown>>(obj: T): T {\n const result = {} as Record<string, unknown>;\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result as T;\n}\n\n// --- Builder Functions ---\n\nexport function article(\n props: Omit<ArticleSchema, '@type'> & { type?: ArticleSchema['@type'] },\n): WithContext<ArticleSchema> {\n const { type = 'Article', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as ArticleSchema);\n}\n\nexport function blogPosting(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'BlogPosting' });\n}\n\nexport function newsArticle(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'NewsArticle' });\n}\n\nexport function product(props: Omit<ProductSchema, '@type'>): WithContext<ProductSchema> {\n return withContext(clean({ '@type': 'Product', ...props }) as ProductSchema);\n}\n\nexport function faqPage(\n questions: Array<{ question: string; answer: string }>,\n): WithContext<FAQPageSchema> {\n const mainEntity: FAQQuestionSchema[] = questions.map((q) => ({\n '@type': 'Question' as const,\n name: q.question,\n acceptedAnswer: {\n '@type': 'Answer' as const,\n text: q.answer,\n },\n }));\n\n return withContext({ '@type': 'FAQPage' as const, mainEntity });\n}\n\nexport function breadcrumbList(\n items: Array<{ name: string; url?: string }>,\n): WithContext<BreadcrumbListSchema> {\n return withContext({\n '@type': 'BreadcrumbList' as const,\n itemListElement: items.map((item, index) =>\n clean({\n '@type': 'ListItem' as const,\n position: index + 1,\n name: item.name,\n item: item.url,\n }),\n ),\n });\n}\n\nexport function localBusiness(\n props: Omit<LocalBusinessSchema, '@type'> & { type?: string },\n): WithContext<LocalBusinessSchema> {\n const { type = 'LocalBusiness', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as LocalBusinessSchema);\n}\n\nexport function organization(\n props: Omit<OrganizationSchema, '@type'>,\n): WithContext<OrganizationSchema> {\n return withContext(clean({ '@type': 'Organization', ...props }) as OrganizationSchema);\n}\n\nexport function person(props: Omit<PersonSchema, '@type'>): WithContext<PersonSchema> {\n return withContext(clean({ '@type': 'Person', ...props }) as PersonSchema);\n}\n\nexport function event(\n props: Omit<EventSchema, '@type'> & { type?: EventSchema['@type'] },\n): WithContext<EventSchema> {\n const { type = 'Event', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as EventSchema);\n}\n\nexport function recipe(props: Omit<RecipeSchema, '@type'>): WithContext<RecipeSchema> {\n return withContext(clean({ '@type': 'Recipe', ...props }) as RecipeSchema);\n}\n\nexport function howTo(props: Omit<HowToSchema, '@type'>): WithContext<HowToSchema> {\n return withContext(clean({ '@type': 'HowTo', ...props }) as HowToSchema);\n}\n\nexport function videoObject(\n props: Omit<VideoObjectSchema, '@type'>,\n): WithContext<VideoObjectSchema> {\n return withContext(clean({ '@type': 'VideoObject', ...props }) as VideoObjectSchema);\n}\n\nexport function course(props: Omit<CourseSchema, '@type'>): WithContext<CourseSchema> {\n return withContext(clean({ '@type': 'Course', ...props }) as CourseSchema);\n}\n\nexport function jobPosting(props: Omit<JobPostingSchema, '@type'>): WithContext<JobPostingSchema> {\n return withContext(clean({ '@type': 'JobPosting', ...props }) as JobPostingSchema);\n}\n\nexport function softwareApp(\n props: Omit<SoftwareAppSchema, '@type'> & { type?: SoftwareAppSchema['@type'] },\n): WithContext<SoftwareAppSchema> {\n const { type = 'SoftwareApplication', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as SoftwareAppSchema);\n}\n\nexport function webSite(props: Omit<WebSiteSchema, '@type'>): WithContext<WebSiteSchema> {\n return withContext(clean({ '@type': 'WebSite', ...props }) as WebSiteSchema);\n}\n\nexport function itemList(props: Omit<ItemListSchema, '@type'>): WithContext<ItemListSchema> {\n return withContext(clean({ '@type': 'ItemList', ...props }) as ItemListSchema);\n}\n\nexport function review(props: Omit<ReviewSchema, '@type'>): WithContext<ReviewSchema> {\n return withContext(clean({ '@type': 'Review', ...props }) as ReviewSchema);\n}\n\nexport function service(props: Omit<ServiceSchema, '@type'>): WithContext<ServiceSchema> {\n return withContext(clean({ '@type': 'Service', ...props }) as ServiceSchema);\n}\n\nexport function brand(props: Omit<BrandSchema, '@type'>): WithContext<BrandSchema> {\n return withContext(clean({ '@type': 'Brand', ...props }) as BrandSchema);\n}\n\nexport function siteNavigationElement(\n props: Omit<SiteNavigationElementSchema, '@type'>,\n): WithContext<SiteNavigationElementSchema> {\n return withContext(\n clean({ '@type': 'SiteNavigationElement', ...props }) as SiteNavigationElementSchema,\n );\n}\n\nexport function imageObject(props: Omit<ImageObject, '@type'>): WithContext<ImageObject> {\n return withContext(clean({ '@type': 'ImageObject', ...props }) as ImageObject);\n}\n\n// --- Schema Graph Builder ---\n\n/**\n * Build a connected schema graph with multiple types.\n *\n * @example\n * ```ts\n * const graph = schemaGraph([\n * { '@type': 'WebSite', name: 'My Site', url: 'https://example.com' },\n * { '@type': 'Organization', name: 'My Org', url: 'https://example.com' },\n * ]);\n * ```\n */\nexport function schemaGraph(schemas: SchemaObject[]): SchemaGraph {\n return {\n '@context': CONTEXT,\n '@graph': schemas,\n };\n}\n\n/**\n * Serialize a schema object to a JSON-LD string safe for use with\n * `dangerouslySetInnerHTML` inside a `<script>` tag.\n *\n * HTML special characters (`<`, `>`, `&`) are escaped to their Unicode\n * escape sequences so that a string value like `\"</script>\"` cannot\n * prematurely close the script tag (XSS vector).\n */\nexport function toJsonLdString(\n schema: WithContext<SchemaObject> | SchemaGraph,\n pretty = false,\n): string {\n return JSON.stringify(schema, null, pretty ? 2 : undefined)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026');\n}\n","// @power-seo/schema — Google Rich Results Validation\n// ----------------------------------------------------------------------------\n\nimport type { SchemaObject } from './types.js';\n\nexport interface ValidationIssue {\n severity: 'error' | 'warning';\n field: string;\n message: string;\n}\n\nexport interface SchemaValidationResult {\n valid: boolean;\n issues: ValidationIssue[];\n}\n\n/**\n * Validate one or more schema objects against Google Rich Results requirements.\n * When an array is passed, each object is validated and all issues are merged.\n */\nexport function validateSchema(schema: SchemaObject | SchemaObject[]): SchemaValidationResult {\n if (Array.isArray(schema)) {\n const allIssues: ValidationIssue[] = [];\n for (const s of schema) {\n const result = validateSchema(s);\n allIssues.push(...result.issues);\n }\n return {\n valid: allIssues.filter((i) => i.severity === 'error').length === 0,\n issues: allIssues,\n };\n }\n\n const issues: ValidationIssue[] = [];\n\n const obj = schema as unknown as Record<string, unknown>;\n\n switch (schema['@type']) {\n case 'Article':\n case 'BlogPosting':\n case 'NewsArticle':\n case 'TechArticle':\n validateArticle(obj, issues);\n break;\n case 'Product':\n validateProduct(obj, issues);\n break;\n case 'FAQPage':\n validateFAQPage(obj, issues);\n break;\n case 'BreadcrumbList':\n validateBreadcrumbList(obj, issues);\n break;\n case 'Event':\n case 'MusicEvent':\n case 'BusinessEvent':\n case 'EducationEvent':\n validateEvent(obj, issues);\n break;\n case 'Recipe':\n validateRecipe(obj, issues);\n break;\n case 'VideoObject':\n validateVideoObject(obj, issues);\n break;\n case 'JobPosting':\n validateJobPosting(obj, issues);\n break;\n case 'LocalBusiness':\n case 'Restaurant':\n case 'Store':\n validateLocalBusiness(obj, issues);\n break;\n case 'Course':\n validateCourse(obj, issues);\n break;\n }\n\n return {\n valid: issues.filter((i) => i.severity === 'error').length === 0,\n issues,\n };\n}\n\nfunction requireField(obj: Record<string, unknown>, field: string, issues: ValidationIssue[]) {\n if (obj[field] === undefined || obj[field] === null || obj[field] === '') {\n issues.push({\n severity: 'error',\n field,\n message: `Required field \"${field}\" is missing.`,\n });\n }\n}\n\nfunction recommendField(obj: Record<string, unknown>, field: string, issues: ValidationIssue[]) {\n if (obj[field] === undefined || obj[field] === null || obj[field] === '') {\n issues.push({\n severity: 'warning',\n field,\n message: `Recommended field \"${field}\" is missing.`,\n });\n }\n}\n\nfunction validateArticle(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'headline', issues);\n requireField(schema, 'author', issues);\n requireField(schema, 'datePublished', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'dateModified', issues);\n recommendField(schema, 'publisher', issues);\n recommendField(schema, 'mainEntityOfPage', issues);\n\n if (typeof schema.headline === 'string' && schema.headline.length > 110) {\n issues.push({\n severity: 'warning',\n field: 'headline',\n message: 'Headline should be under 110 characters for Google Rich Results.',\n });\n }\n}\n\nfunction validateProduct(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'offers', issues);\n recommendField(schema, 'aggregateRating', issues);\n recommendField(schema, 'brand', issues);\n recommendField(schema, 'sku', issues);\n}\n\nfunction validateFAQPage(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n const mainEntity = schema.mainEntity as Array<Record<string, unknown>> | undefined;\n if (!mainEntity || !Array.isArray(mainEntity) || mainEntity.length === 0) {\n issues.push({\n severity: 'error',\n field: 'mainEntity',\n message: 'FAQPage requires at least one Question in mainEntity.',\n });\n return;\n }\n\n for (let i = 0; i < mainEntity.length; i++) {\n const q = mainEntity[i]!;\n if (!q.name) {\n issues.push({\n severity: 'error',\n field: `mainEntity[${i}].name`,\n message: `Question ${i + 1} is missing \"name\" (the question text).`,\n });\n }\n const answer = q.acceptedAnswer as Record<string, unknown> | undefined;\n if (!answer?.text) {\n issues.push({\n severity: 'error',\n field: `mainEntity[${i}].acceptedAnswer.text`,\n message: `Question ${i + 1} is missing an answer text.`,\n });\n }\n }\n}\n\nfunction validateBreadcrumbList(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n const items = schema.itemListElement as Array<Record<string, unknown>> | undefined;\n if (!items || !Array.isArray(items) || items.length === 0) {\n issues.push({\n severity: 'error',\n field: 'itemListElement',\n message: 'BreadcrumbList requires at least one ListItem.',\n });\n }\n}\n\nfunction validateEvent(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'startDate', issues);\n requireField(schema, 'location', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'offers', issues);\n recommendField(schema, 'organizer', issues);\n}\n\nfunction validateRecipe(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'image', issues);\n requireField(schema, 'recipeIngredient', issues);\n requireField(schema, 'recipeInstructions', issues);\n recommendField(schema, 'author', issues);\n recommendField(schema, 'datePublished', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'prepTime', issues);\n recommendField(schema, 'totalTime', issues);\n}\n\nfunction validateVideoObject(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'description', issues);\n requireField(schema, 'thumbnailUrl', issues);\n requireField(schema, 'uploadDate', issues);\n recommendField(schema, 'contentUrl', issues);\n recommendField(schema, 'duration', issues);\n}\n\nfunction validateJobPosting(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'title', issues);\n requireField(schema, 'description', issues);\n requireField(schema, 'datePosted', issues);\n requireField(schema, 'hiringOrganization', issues);\n recommendField(schema, 'validThrough', issues);\n recommendField(schema, 'employmentType', issues);\n recommendField(schema, 'baseSalary', issues);\n}\n\nfunction validateLocalBusiness(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'address', issues);\n recommendField(schema, 'telephone', issues);\n recommendField(schema, 'openingHoursSpecification', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'url', issues);\n recommendField(schema, 'geo', issues);\n}\n\nfunction validateCourse(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'description', issues);\n recommendField(schema, 'provider', issues);\n recommendField(schema, 'offers', issues);\n}\n"],"mappings":"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","names":[]} |
+15
-7
@@ -1,3 +0,3 @@ | ||
| import { A as ArticleSchema, W as WithContext, B as BreadcrumbListSchema, C as CourseSchema, E as EventSchema, F as FAQPageSchema, H as HowToSchema, I as ItemListSchema, J as JobPostingSchema, L as LocalBusinessSchema, O as OrganizationSchema, P as PersonSchema, a as ProductSchema, R as RecipeSchema, b as ReviewSchema, S as SchemaObject, c as SchemaGraph, d as ServiceSchema, e as SoftwareAppSchema, V as VideoObjectSchema, f as WebSiteSchema } from './types-DZpjF5KF.cjs'; | ||
| export { g as AggregateRatingSchema, h as BreadcrumbItem, i as ContactPoint, j as CourseInstance, k as FAQQuestionSchema, G as GeoCoordinates, l as HowToStep, m as HowToSupply, n as HowToTool, o as ImageObject, p as JsonLdBase, q as ListItem, M as MonetaryAmount, N as NutritionInfo, r as OfferSchema, s as OpeningHours, t as PostalAddress, u as RatingSchema, v as SearchActionSchema, T as ThingBase } from './types-DZpjF5KF.cjs'; | ||
| import { A as ArticleSchema, W as WithContext, B as BrandSchema, a as BreadcrumbListSchema, C as CourseSchema, E as EventSchema, F as FAQPageSchema, H as HowToSchema, I as ImageObject, b as ItemListSchema, J as JobPostingSchema, L as LocalBusinessSchema, O as OrganizationSchema, P as PersonSchema, c as ProductSchema, R as RecipeSchema, d as ReviewSchema, S as SchemaObject, e as SchemaGraph, f as ServiceSchema, g as SiteNavigationElementSchema, h as SoftwareAppSchema, V as VideoObjectSchema, i as WebSiteSchema } from './types-CGc2j4fj.cjs'; | ||
| export { j as AggregateRatingSchema, k as BreadcrumbItem, l as ContactPoint, m as CourseInstance, n as FAQQuestionSchema, G as GeoCoordinates, o as HowToStep, p as HowToSupply, q as HowToTool, r as JsonLdBase, s as ListItem, M as MonetaryAmount, N as NutritionInfo, t as OfferSchema, u as OpeningHours, v as PostalAddress, w as RatingSchema, x as SearchActionSchema, T as ThingBase } from './types-CGc2j4fj.cjs'; | ||
@@ -38,2 +38,5 @@ declare function article(props: Omit<ArticleSchema, '@type'> & { | ||
| declare function service(props: Omit<ServiceSchema, '@type'>): WithContext<ServiceSchema>; | ||
| declare function brand(props: Omit<BrandSchema, '@type'>): WithContext<BrandSchema>; | ||
| declare function siteNavigationElement(props: Omit<SiteNavigationElementSchema, '@type'>): WithContext<SiteNavigationElementSchema>; | ||
| declare function imageObject(props: Omit<ImageObject, '@type'>): WithContext<ImageObject>; | ||
| /** | ||
@@ -52,3 +55,8 @@ * Build a connected schema graph with multiple types. | ||
| /** | ||
| * Serialize a schema object to a JSON-LD string. | ||
| * Serialize a schema object to a JSON-LD string safe for use with | ||
| * `dangerouslySetInnerHTML` inside a `<script>` tag. | ||
| * | ||
| * HTML special characters (`<`, `>`, `&`) are escaped to their Unicode | ||
| * escape sequences so that a string value like `"</script>"` cannot | ||
| * prematurely close the script tag (XSS vector). | ||
| */ | ||
@@ -67,7 +75,7 @@ declare function toJsonLdString(schema: WithContext<SchemaObject> | SchemaGraph, pretty?: boolean): string; | ||
| /** | ||
| * Validate a schema object against Google Rich Results requirements. | ||
| * This checks required fields beyond basic Schema.org conformance. | ||
| * Validate one or more schema objects against Google Rich Results requirements. | ||
| * When an array is passed, each object is validated and all issues are merged. | ||
| */ | ||
| declare function validateSchema(schema: SchemaObject): SchemaValidationResult; | ||
| declare function validateSchema(schema: SchemaObject | SchemaObject[]): SchemaValidationResult; | ||
| export { ArticleSchema, BreadcrumbListSchema, CourseSchema, EventSchema, FAQPageSchema, HowToSchema, ItemListSchema, JobPostingSchema, LocalBusinessSchema, OrganizationSchema, PersonSchema, ProductSchema, RecipeSchema, ReviewSchema, SchemaGraph, SchemaObject, type SchemaValidationResult, ServiceSchema, SoftwareAppSchema, type ValidationIssue, VideoObjectSchema, WebSiteSchema, WithContext, article, blogPosting, breadcrumbList, course, event, faqPage, howTo, itemList, jobPosting, localBusiness, newsArticle, organization, person, product, recipe, review, schemaGraph, service, softwareApp, toJsonLdString, validateSchema, videoObject, webSite }; | ||
| export { ArticleSchema, BrandSchema, BreadcrumbListSchema, CourseSchema, EventSchema, FAQPageSchema, HowToSchema, ImageObject, ItemListSchema, JobPostingSchema, LocalBusinessSchema, OrganizationSchema, PersonSchema, ProductSchema, RecipeSchema, ReviewSchema, SchemaGraph, SchemaObject, type SchemaValidationResult, ServiceSchema, SiteNavigationElementSchema, SoftwareAppSchema, type ValidationIssue, VideoObjectSchema, WebSiteSchema, WithContext, article, blogPosting, brand, breadcrumbList, course, event, faqPage, howTo, imageObject, itemList, jobPosting, localBusiness, newsArticle, organization, person, product, recipe, review, schemaGraph, service, siteNavigationElement, softwareApp, toJsonLdString, validateSchema, videoObject, webSite }; |
+15
-7
@@ -1,3 +0,3 @@ | ||
| import { A as ArticleSchema, W as WithContext, B as BreadcrumbListSchema, C as CourseSchema, E as EventSchema, F as FAQPageSchema, H as HowToSchema, I as ItemListSchema, J as JobPostingSchema, L as LocalBusinessSchema, O as OrganizationSchema, P as PersonSchema, a as ProductSchema, R as RecipeSchema, b as ReviewSchema, S as SchemaObject, c as SchemaGraph, d as ServiceSchema, e as SoftwareAppSchema, V as VideoObjectSchema, f as WebSiteSchema } from './types-DZpjF5KF.js'; | ||
| export { g as AggregateRatingSchema, h as BreadcrumbItem, i as ContactPoint, j as CourseInstance, k as FAQQuestionSchema, G as GeoCoordinates, l as HowToStep, m as HowToSupply, n as HowToTool, o as ImageObject, p as JsonLdBase, q as ListItem, M as MonetaryAmount, N as NutritionInfo, r as OfferSchema, s as OpeningHours, t as PostalAddress, u as RatingSchema, v as SearchActionSchema, T as ThingBase } from './types-DZpjF5KF.js'; | ||
| import { A as ArticleSchema, W as WithContext, B as BrandSchema, a as BreadcrumbListSchema, C as CourseSchema, E as EventSchema, F as FAQPageSchema, H as HowToSchema, I as ImageObject, b as ItemListSchema, J as JobPostingSchema, L as LocalBusinessSchema, O as OrganizationSchema, P as PersonSchema, c as ProductSchema, R as RecipeSchema, d as ReviewSchema, S as SchemaObject, e as SchemaGraph, f as ServiceSchema, g as SiteNavigationElementSchema, h as SoftwareAppSchema, V as VideoObjectSchema, i as WebSiteSchema } from './types-CGc2j4fj.js'; | ||
| export { j as AggregateRatingSchema, k as BreadcrumbItem, l as ContactPoint, m as CourseInstance, n as FAQQuestionSchema, G as GeoCoordinates, o as HowToStep, p as HowToSupply, q as HowToTool, r as JsonLdBase, s as ListItem, M as MonetaryAmount, N as NutritionInfo, t as OfferSchema, u as OpeningHours, v as PostalAddress, w as RatingSchema, x as SearchActionSchema, T as ThingBase } from './types-CGc2j4fj.js'; | ||
@@ -38,2 +38,5 @@ declare function article(props: Omit<ArticleSchema, '@type'> & { | ||
| declare function service(props: Omit<ServiceSchema, '@type'>): WithContext<ServiceSchema>; | ||
| declare function brand(props: Omit<BrandSchema, '@type'>): WithContext<BrandSchema>; | ||
| declare function siteNavigationElement(props: Omit<SiteNavigationElementSchema, '@type'>): WithContext<SiteNavigationElementSchema>; | ||
| declare function imageObject(props: Omit<ImageObject, '@type'>): WithContext<ImageObject>; | ||
| /** | ||
@@ -52,3 +55,8 @@ * Build a connected schema graph with multiple types. | ||
| /** | ||
| * Serialize a schema object to a JSON-LD string. | ||
| * Serialize a schema object to a JSON-LD string safe for use with | ||
| * `dangerouslySetInnerHTML` inside a `<script>` tag. | ||
| * | ||
| * HTML special characters (`<`, `>`, `&`) are escaped to their Unicode | ||
| * escape sequences so that a string value like `"</script>"` cannot | ||
| * prematurely close the script tag (XSS vector). | ||
| */ | ||
@@ -67,7 +75,7 @@ declare function toJsonLdString(schema: WithContext<SchemaObject> | SchemaGraph, pretty?: boolean): string; | ||
| /** | ||
| * Validate a schema object against Google Rich Results requirements. | ||
| * This checks required fields beyond basic Schema.org conformance. | ||
| * Validate one or more schema objects against Google Rich Results requirements. | ||
| * When an array is passed, each object is validated and all issues are merged. | ||
| */ | ||
| declare function validateSchema(schema: SchemaObject): SchemaValidationResult; | ||
| declare function validateSchema(schema: SchemaObject | SchemaObject[]): SchemaValidationResult; | ||
| export { ArticleSchema, BreadcrumbListSchema, CourseSchema, EventSchema, FAQPageSchema, HowToSchema, ItemListSchema, JobPostingSchema, LocalBusinessSchema, OrganizationSchema, PersonSchema, ProductSchema, RecipeSchema, ReviewSchema, SchemaGraph, SchemaObject, type SchemaValidationResult, ServiceSchema, SoftwareAppSchema, type ValidationIssue, VideoObjectSchema, WebSiteSchema, WithContext, article, blogPosting, breadcrumbList, course, event, faqPage, howTo, itemList, jobPosting, localBusiness, newsArticle, organization, person, product, recipe, review, schemaGraph, service, softwareApp, toJsonLdString, validateSchema, videoObject, webSite }; | ||
| export { ArticleSchema, BrandSchema, BreadcrumbListSchema, CourseSchema, EventSchema, FAQPageSchema, HowToSchema, ImageObject, ItemListSchema, JobPostingSchema, LocalBusinessSchema, OrganizationSchema, PersonSchema, ProductSchema, RecipeSchema, ReviewSchema, SchemaGraph, SchemaObject, type SchemaValidationResult, ServiceSchema, SiteNavigationElementSchema, SoftwareAppSchema, type ValidationIssue, VideoObjectSchema, WebSiteSchema, WithContext, article, blogPosting, brand, breadcrumbList, course, event, faqPage, howTo, imageObject, itemList, jobPosting, localBusiness, newsArticle, organization, person, product, recipe, review, schemaGraph, service, siteNavigationElement, softwareApp, toJsonLdString, validateSchema, videoObject, webSite }; |
+51
-4
@@ -97,2 +97,13 @@ // src/builders.ts | ||
| } | ||
| function brand(props) { | ||
| return withContext(clean({ "@type": "Brand", ...props })); | ||
| } | ||
| function siteNavigationElement(props) { | ||
| return withContext( | ||
| clean({ "@type": "SiteNavigationElement", ...props }) | ||
| ); | ||
| } | ||
| function imageObject(props) { | ||
| return withContext(clean({ "@type": "ImageObject", ...props })); | ||
| } | ||
| function schemaGraph(schemas) { | ||
@@ -105,3 +116,3 @@ return { | ||
| function toJsonLdString(schema, pretty = false) { | ||
| return JSON.stringify(schema, null, pretty ? 2 : void 0); | ||
| return JSON.stringify(schema, null, pretty ? 2 : void 0).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026"); | ||
| } | ||
@@ -111,2 +122,13 @@ | ||
| function validateSchema(schema) { | ||
| if (Array.isArray(schema)) { | ||
| const allIssues = []; | ||
| for (const s of schema) { | ||
| const result = validateSchema(s); | ||
| allIssues.push(...result.issues); | ||
| } | ||
| return { | ||
| valid: allIssues.filter((i) => i.severity === "error").length === 0, | ||
| issues: allIssues | ||
| }; | ||
| } | ||
| const issues = []; | ||
@@ -293,5 +315,30 @@ const obj = schema; | ||
| } | ||
| export { article, blogPosting, breadcrumbList, course, event, faqPage, howTo, itemList, jobPosting, localBusiness, newsArticle, organization, person, product, recipe, review, schemaGraph, service, softwareApp, toJsonLdString, validateSchema, videoObject, webSite }; | ||
| //# sourceMappingURL=index.js.map | ||
| export { | ||
| article, | ||
| blogPosting, | ||
| brand, | ||
| breadcrumbList, | ||
| course, | ||
| event, | ||
| faqPage, | ||
| howTo, | ||
| imageObject, | ||
| itemList, | ||
| jobPosting, | ||
| localBusiness, | ||
| newsArticle, | ||
| organization, | ||
| person, | ||
| product, | ||
| recipe, | ||
| review, | ||
| schemaGraph, | ||
| service, | ||
| siteNavigationElement, | ||
| softwareApp, | ||
| toJsonLdString, | ||
| validateSchema, | ||
| videoObject, | ||
| webSite | ||
| }; | ||
| //# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/builders.ts","../src/validation.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// ============================================================================\n// @power-seo/schema — JSON-LD Builder Functions\n// ============================================================================\n\nimport type {\n WithContext,\n ArticleSchema,\n ProductSchema,\n FAQPageSchema,\n FAQQuestionSchema,\n BreadcrumbListSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n PersonSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ItemListSchema,\n ReviewSchema,\n ServiceSchema,\n SchemaGraph,\n SchemaObject,\n} from './types.js';\n\nconst CONTEXT = 'https://schema.org' as const;\n\n/** Add @context to a schema object */\nfunction withContext<T extends { '@type': string }>(\n schema: T,\n): WithContext<T & { '@type': string }> {\n return { '@context': CONTEXT, ...schema };\n}\n\n/** Remove undefined values from an object */\nfunction clean<T extends Record<string, unknown>>(obj: T): T {\n const result = {} as Record<string, unknown>;\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result as T;\n}\n\n// --- Builder Functions ---\n\nexport function article(\n props: Omit<ArticleSchema, '@type'> & { type?: ArticleSchema['@type'] },\n): WithContext<ArticleSchema> {\n const { type = 'Article', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as ArticleSchema);\n}\n\nexport function blogPosting(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'BlogPosting' });\n}\n\nexport function newsArticle(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'NewsArticle' });\n}\n\nexport function product(props: Omit<ProductSchema, '@type'>): WithContext<ProductSchema> {\n return withContext(clean({ '@type': 'Product', ...props }) as ProductSchema);\n}\n\nexport function faqPage(\n questions: Array<{ question: string; answer: string }>,\n): WithContext<FAQPageSchema> {\n const mainEntity: FAQQuestionSchema[] = questions.map((q) => ({\n '@type': 'Question' as const,\n name: q.question,\n acceptedAnswer: {\n '@type': 'Answer' as const,\n text: q.answer,\n },\n }));\n\n return withContext({ '@type': 'FAQPage' as const, mainEntity });\n}\n\nexport function breadcrumbList(\n items: Array<{ name: string; url?: string }>,\n): WithContext<BreadcrumbListSchema> {\n return withContext({\n '@type': 'BreadcrumbList' as const,\n itemListElement: items.map((item, index) =>\n clean({\n '@type': 'ListItem' as const,\n position: index + 1,\n name: item.name,\n item: item.url,\n }),\n ),\n });\n}\n\nexport function localBusiness(\n props: Omit<LocalBusinessSchema, '@type'> & { type?: string },\n): WithContext<LocalBusinessSchema> {\n const { type = 'LocalBusiness', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as LocalBusinessSchema);\n}\n\nexport function organization(\n props: Omit<OrganizationSchema, '@type'>,\n): WithContext<OrganizationSchema> {\n return withContext(clean({ '@type': 'Organization', ...props }) as OrganizationSchema);\n}\n\nexport function person(props: Omit<PersonSchema, '@type'>): WithContext<PersonSchema> {\n return withContext(clean({ '@type': 'Person', ...props }) as PersonSchema);\n}\n\nexport function event(\n props: Omit<EventSchema, '@type'> & { type?: EventSchema['@type'] },\n): WithContext<EventSchema> {\n const { type = 'Event', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as EventSchema);\n}\n\nexport function recipe(props: Omit<RecipeSchema, '@type'>): WithContext<RecipeSchema> {\n return withContext(clean({ '@type': 'Recipe', ...props }) as RecipeSchema);\n}\n\nexport function howTo(props: Omit<HowToSchema, '@type'>): WithContext<HowToSchema> {\n return withContext(clean({ '@type': 'HowTo', ...props }) as HowToSchema);\n}\n\nexport function videoObject(\n props: Omit<VideoObjectSchema, '@type'>,\n): WithContext<VideoObjectSchema> {\n return withContext(clean({ '@type': 'VideoObject', ...props }) as VideoObjectSchema);\n}\n\nexport function course(props: Omit<CourseSchema, '@type'>): WithContext<CourseSchema> {\n return withContext(clean({ '@type': 'Course', ...props }) as CourseSchema);\n}\n\nexport function jobPosting(props: Omit<JobPostingSchema, '@type'>): WithContext<JobPostingSchema> {\n return withContext(clean({ '@type': 'JobPosting', ...props }) as JobPostingSchema);\n}\n\nexport function softwareApp(\n props: Omit<SoftwareAppSchema, '@type'> & { type?: SoftwareAppSchema['@type'] },\n): WithContext<SoftwareAppSchema> {\n const { type = 'SoftwareApplication', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as SoftwareAppSchema);\n}\n\nexport function webSite(props: Omit<WebSiteSchema, '@type'>): WithContext<WebSiteSchema> {\n return withContext(clean({ '@type': 'WebSite', ...props }) as WebSiteSchema);\n}\n\nexport function itemList(props: Omit<ItemListSchema, '@type'>): WithContext<ItemListSchema> {\n return withContext(clean({ '@type': 'ItemList', ...props }) as ItemListSchema);\n}\n\nexport function review(props: Omit<ReviewSchema, '@type'>): WithContext<ReviewSchema> {\n return withContext(clean({ '@type': 'Review', ...props }) as ReviewSchema);\n}\n\nexport function service(props: Omit<ServiceSchema, '@type'>): WithContext<ServiceSchema> {\n return withContext(clean({ '@type': 'Service', ...props }) as ServiceSchema);\n}\n\n// --- Schema Graph Builder ---\n\n/**\n * Build a connected schema graph with multiple types.\n *\n * @example\n * ```ts\n * const graph = schemaGraph([\n * { '@type': 'WebSite', name: 'My Site', url: 'https://example.com' },\n * { '@type': 'Organization', name: 'My Org', url: 'https://example.com' },\n * ]);\n * ```\n */\nexport function schemaGraph(schemas: SchemaObject[]): SchemaGraph {\n return {\n '@context': CONTEXT,\n '@graph': schemas,\n };\n}\n\n/**\n * Serialize a schema object to a JSON-LD string.\n */\nexport function toJsonLdString(\n schema: WithContext<SchemaObject> | SchemaGraph,\n pretty = false,\n): string {\n return JSON.stringify(schema, null, pretty ? 2 : undefined);\n}\n","// ============================================================================\n// @power-seo/schema — Google Rich Results Validation\n// ============================================================================\n\nimport type { SchemaObject } from './types.js';\n\nexport interface ValidationIssue {\n severity: 'error' | 'warning';\n field: string;\n message: string;\n}\n\nexport interface SchemaValidationResult {\n valid: boolean;\n issues: ValidationIssue[];\n}\n\n/**\n * Validate a schema object against Google Rich Results requirements.\n * This checks required fields beyond basic Schema.org conformance.\n */\nexport function validateSchema(schema: SchemaObject): SchemaValidationResult {\n const issues: ValidationIssue[] = [];\n\n const obj = schema as unknown as Record<string, unknown>;\n\n switch (schema['@type']) {\n case 'Article':\n case 'BlogPosting':\n case 'NewsArticle':\n case 'TechArticle':\n validateArticle(obj, issues);\n break;\n case 'Product':\n validateProduct(obj, issues);\n break;\n case 'FAQPage':\n validateFAQPage(obj, issues);\n break;\n case 'BreadcrumbList':\n validateBreadcrumbList(obj, issues);\n break;\n case 'Event':\n case 'MusicEvent':\n case 'BusinessEvent':\n case 'EducationEvent':\n validateEvent(obj, issues);\n break;\n case 'Recipe':\n validateRecipe(obj, issues);\n break;\n case 'VideoObject':\n validateVideoObject(obj, issues);\n break;\n case 'JobPosting':\n validateJobPosting(obj, issues);\n break;\n case 'LocalBusiness':\n case 'Restaurant':\n case 'Store':\n validateLocalBusiness(obj, issues);\n break;\n case 'Course':\n validateCourse(obj, issues);\n break;\n }\n\n return {\n valid: issues.filter((i) => i.severity === 'error').length === 0,\n issues,\n };\n}\n\nfunction requireField(obj: Record<string, unknown>, field: string, issues: ValidationIssue[]) {\n if (obj[field] === undefined || obj[field] === null || obj[field] === '') {\n issues.push({\n severity: 'error',\n field,\n message: `Required field \"${field}\" is missing.`,\n });\n }\n}\n\nfunction recommendField(obj: Record<string, unknown>, field: string, issues: ValidationIssue[]) {\n if (obj[field] === undefined || obj[field] === null || obj[field] === '') {\n issues.push({\n severity: 'warning',\n field,\n message: `Recommended field \"${field}\" is missing.`,\n });\n }\n}\n\nfunction validateArticle(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'headline', issues);\n requireField(schema, 'author', issues);\n requireField(schema, 'datePublished', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'dateModified', issues);\n recommendField(schema, 'publisher', issues);\n recommendField(schema, 'mainEntityOfPage', issues);\n\n if (typeof schema.headline === 'string' && schema.headline.length > 110) {\n issues.push({\n severity: 'warning',\n field: 'headline',\n message: 'Headline should be under 110 characters for Google Rich Results.',\n });\n }\n}\n\nfunction validateProduct(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'offers', issues);\n recommendField(schema, 'aggregateRating', issues);\n recommendField(schema, 'brand', issues);\n recommendField(schema, 'sku', issues);\n}\n\nfunction validateFAQPage(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n const mainEntity = schema.mainEntity as Array<Record<string, unknown>> | undefined;\n if (!mainEntity || !Array.isArray(mainEntity) || mainEntity.length === 0) {\n issues.push({\n severity: 'error',\n field: 'mainEntity',\n message: 'FAQPage requires at least one Question in mainEntity.',\n });\n return;\n }\n\n for (let i = 0; i < mainEntity.length; i++) {\n const q = mainEntity[i]!;\n if (!q.name) {\n issues.push({\n severity: 'error',\n field: `mainEntity[${i}].name`,\n message: `Question ${i + 1} is missing \"name\" (the question text).`,\n });\n }\n const answer = q.acceptedAnswer as Record<string, unknown> | undefined;\n if (!answer?.text) {\n issues.push({\n severity: 'error',\n field: `mainEntity[${i}].acceptedAnswer.text`,\n message: `Question ${i + 1} is missing an answer text.`,\n });\n }\n }\n}\n\nfunction validateBreadcrumbList(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n const items = schema.itemListElement as Array<Record<string, unknown>> | undefined;\n if (!items || !Array.isArray(items) || items.length === 0) {\n issues.push({\n severity: 'error',\n field: 'itemListElement',\n message: 'BreadcrumbList requires at least one ListItem.',\n });\n }\n}\n\nfunction validateEvent(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'startDate', issues);\n requireField(schema, 'location', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'offers', issues);\n recommendField(schema, 'organizer', issues);\n}\n\nfunction validateRecipe(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'image', issues);\n requireField(schema, 'recipeIngredient', issues);\n requireField(schema, 'recipeInstructions', issues);\n recommendField(schema, 'author', issues);\n recommendField(schema, 'datePublished', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'prepTime', issues);\n recommendField(schema, 'totalTime', issues);\n}\n\nfunction validateVideoObject(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'description', issues);\n requireField(schema, 'thumbnailUrl', issues);\n requireField(schema, 'uploadDate', issues);\n recommendField(schema, 'contentUrl', issues);\n recommendField(schema, 'duration', issues);\n}\n\nfunction validateJobPosting(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'title', issues);\n requireField(schema, 'description', issues);\n requireField(schema, 'datePosted', issues);\n requireField(schema, 'hiringOrganization', issues);\n recommendField(schema, 'validThrough', issues);\n recommendField(schema, 'employmentType', issues);\n recommendField(schema, 'baseSalary', issues);\n}\n\nfunction validateLocalBusiness(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'address', issues);\n recommendField(schema, 'telephone', issues);\n recommendField(schema, 'openingHoursSpecification', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'url', issues);\n recommendField(schema, 'geo', issues);\n}\n\nfunction validateCourse(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'description', issues);\n recommendField(schema, 'provider', issues);\n recommendField(schema, 'offers', issues);\n}\n"]} | ||
| {"version":3,"sources":["../src/builders.ts","../src/validation.ts"],"sourcesContent":["// @power-seo/schema — JSON-LD Builder Functions\n// ----------------------------------------------------------------------------\n\nimport type {\n WithContext,\n ArticleSchema,\n ProductSchema,\n FAQPageSchema,\n FAQQuestionSchema,\n BreadcrumbListSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n PersonSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ItemListSchema,\n ReviewSchema,\n ServiceSchema,\n BrandSchema,\n SiteNavigationElementSchema,\n ImageObject,\n SchemaGraph,\n SchemaObject,\n} from './types.js';\n\nconst CONTEXT = 'https://schema.org' as const;\n\n/** Add @context to a schema object */\nfunction withContext<T extends { '@type': string }>(\n schema: T,\n): WithContext<T & { '@type': string }> {\n return { '@context': CONTEXT, ...schema };\n}\n\n/** Remove undefined values from an object */\nfunction clean<T extends Record<string, unknown>>(obj: T): T {\n const result = {} as Record<string, unknown>;\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result as T;\n}\n\n// --- Builder Functions ---\n\nexport function article(\n props: Omit<ArticleSchema, '@type'> & { type?: ArticleSchema['@type'] },\n): WithContext<ArticleSchema> {\n const { type = 'Article', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as ArticleSchema);\n}\n\nexport function blogPosting(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'BlogPosting' });\n}\n\nexport function newsArticle(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'NewsArticle' });\n}\n\nexport function product(props: Omit<ProductSchema, '@type'>): WithContext<ProductSchema> {\n return withContext(clean({ '@type': 'Product', ...props }) as ProductSchema);\n}\n\nexport function faqPage(\n questions: Array<{ question: string; answer: string }>,\n): WithContext<FAQPageSchema> {\n const mainEntity: FAQQuestionSchema[] = questions.map((q) => ({\n '@type': 'Question' as const,\n name: q.question,\n acceptedAnswer: {\n '@type': 'Answer' as const,\n text: q.answer,\n },\n }));\n\n return withContext({ '@type': 'FAQPage' as const, mainEntity });\n}\n\nexport function breadcrumbList(\n items: Array<{ name: string; url?: string }>,\n): WithContext<BreadcrumbListSchema> {\n return withContext({\n '@type': 'BreadcrumbList' as const,\n itemListElement: items.map((item, index) =>\n clean({\n '@type': 'ListItem' as const,\n position: index + 1,\n name: item.name,\n item: item.url,\n }),\n ),\n });\n}\n\nexport function localBusiness(\n props: Omit<LocalBusinessSchema, '@type'> & { type?: string },\n): WithContext<LocalBusinessSchema> {\n const { type = 'LocalBusiness', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as LocalBusinessSchema);\n}\n\nexport function organization(\n props: Omit<OrganizationSchema, '@type'>,\n): WithContext<OrganizationSchema> {\n return withContext(clean({ '@type': 'Organization', ...props }) as OrganizationSchema);\n}\n\nexport function person(props: Omit<PersonSchema, '@type'>): WithContext<PersonSchema> {\n return withContext(clean({ '@type': 'Person', ...props }) as PersonSchema);\n}\n\nexport function event(\n props: Omit<EventSchema, '@type'> & { type?: EventSchema['@type'] },\n): WithContext<EventSchema> {\n const { type = 'Event', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as EventSchema);\n}\n\nexport function recipe(props: Omit<RecipeSchema, '@type'>): WithContext<RecipeSchema> {\n return withContext(clean({ '@type': 'Recipe', ...props }) as RecipeSchema);\n}\n\nexport function howTo(props: Omit<HowToSchema, '@type'>): WithContext<HowToSchema> {\n return withContext(clean({ '@type': 'HowTo', ...props }) as HowToSchema);\n}\n\nexport function videoObject(\n props: Omit<VideoObjectSchema, '@type'>,\n): WithContext<VideoObjectSchema> {\n return withContext(clean({ '@type': 'VideoObject', ...props }) as VideoObjectSchema);\n}\n\nexport function course(props: Omit<CourseSchema, '@type'>): WithContext<CourseSchema> {\n return withContext(clean({ '@type': 'Course', ...props }) as CourseSchema);\n}\n\nexport function jobPosting(props: Omit<JobPostingSchema, '@type'>): WithContext<JobPostingSchema> {\n return withContext(clean({ '@type': 'JobPosting', ...props }) as JobPostingSchema);\n}\n\nexport function softwareApp(\n props: Omit<SoftwareAppSchema, '@type'> & { type?: SoftwareAppSchema['@type'] },\n): WithContext<SoftwareAppSchema> {\n const { type = 'SoftwareApplication', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as SoftwareAppSchema);\n}\n\nexport function webSite(props: Omit<WebSiteSchema, '@type'>): WithContext<WebSiteSchema> {\n return withContext(clean({ '@type': 'WebSite', ...props }) as WebSiteSchema);\n}\n\nexport function itemList(props: Omit<ItemListSchema, '@type'>): WithContext<ItemListSchema> {\n return withContext(clean({ '@type': 'ItemList', ...props }) as ItemListSchema);\n}\n\nexport function review(props: Omit<ReviewSchema, '@type'>): WithContext<ReviewSchema> {\n return withContext(clean({ '@type': 'Review', ...props }) as ReviewSchema);\n}\n\nexport function service(props: Omit<ServiceSchema, '@type'>): WithContext<ServiceSchema> {\n return withContext(clean({ '@type': 'Service', ...props }) as ServiceSchema);\n}\n\nexport function brand(props: Omit<BrandSchema, '@type'>): WithContext<BrandSchema> {\n return withContext(clean({ '@type': 'Brand', ...props }) as BrandSchema);\n}\n\nexport function siteNavigationElement(\n props: Omit<SiteNavigationElementSchema, '@type'>,\n): WithContext<SiteNavigationElementSchema> {\n return withContext(\n clean({ '@type': 'SiteNavigationElement', ...props }) as SiteNavigationElementSchema,\n );\n}\n\nexport function imageObject(props: Omit<ImageObject, '@type'>): WithContext<ImageObject> {\n return withContext(clean({ '@type': 'ImageObject', ...props }) as ImageObject);\n}\n\n// --- Schema Graph Builder ---\n\n/**\n * Build a connected schema graph with multiple types.\n *\n * @example\n * ```ts\n * const graph = schemaGraph([\n * { '@type': 'WebSite', name: 'My Site', url: 'https://example.com' },\n * { '@type': 'Organization', name: 'My Org', url: 'https://example.com' },\n * ]);\n * ```\n */\nexport function schemaGraph(schemas: SchemaObject[]): SchemaGraph {\n return {\n '@context': CONTEXT,\n '@graph': schemas,\n };\n}\n\n/**\n * Serialize a schema object to a JSON-LD string safe for use with\n * `dangerouslySetInnerHTML` inside a `<script>` tag.\n *\n * HTML special characters (`<`, `>`, `&`) are escaped to their Unicode\n * escape sequences so that a string value like `\"</script>\"` cannot\n * prematurely close the script tag (XSS vector).\n */\nexport function toJsonLdString(\n schema: WithContext<SchemaObject> | SchemaGraph,\n pretty = false,\n): string {\n return JSON.stringify(schema, null, pretty ? 2 : undefined)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026');\n}\n","// @power-seo/schema — Google Rich Results Validation\n// ----------------------------------------------------------------------------\n\nimport type { SchemaObject } from './types.js';\n\nexport interface ValidationIssue {\n severity: 'error' | 'warning';\n field: string;\n message: string;\n}\n\nexport interface SchemaValidationResult {\n valid: boolean;\n issues: ValidationIssue[];\n}\n\n/**\n * Validate one or more schema objects against Google Rich Results requirements.\n * When an array is passed, each object is validated and all issues are merged.\n */\nexport function validateSchema(schema: SchemaObject | SchemaObject[]): SchemaValidationResult {\n if (Array.isArray(schema)) {\n const allIssues: ValidationIssue[] = [];\n for (const s of schema) {\n const result = validateSchema(s);\n allIssues.push(...result.issues);\n }\n return {\n valid: allIssues.filter((i) => i.severity === 'error').length === 0,\n issues: allIssues,\n };\n }\n\n const issues: ValidationIssue[] = [];\n\n const obj = schema as unknown as Record<string, unknown>;\n\n switch (schema['@type']) {\n case 'Article':\n case 'BlogPosting':\n case 'NewsArticle':\n case 'TechArticle':\n validateArticle(obj, issues);\n break;\n case 'Product':\n validateProduct(obj, issues);\n break;\n case 'FAQPage':\n validateFAQPage(obj, issues);\n break;\n case 'BreadcrumbList':\n validateBreadcrumbList(obj, issues);\n break;\n case 'Event':\n case 'MusicEvent':\n case 'BusinessEvent':\n case 'EducationEvent':\n validateEvent(obj, issues);\n break;\n case 'Recipe':\n validateRecipe(obj, issues);\n break;\n case 'VideoObject':\n validateVideoObject(obj, issues);\n break;\n case 'JobPosting':\n validateJobPosting(obj, issues);\n break;\n case 'LocalBusiness':\n case 'Restaurant':\n case 'Store':\n validateLocalBusiness(obj, issues);\n break;\n case 'Course':\n validateCourse(obj, issues);\n break;\n }\n\n return {\n valid: issues.filter((i) => i.severity === 'error').length === 0,\n issues,\n };\n}\n\nfunction requireField(obj: Record<string, unknown>, field: string, issues: ValidationIssue[]) {\n if (obj[field] === undefined || obj[field] === null || obj[field] === '') {\n issues.push({\n severity: 'error',\n field,\n message: `Required field \"${field}\" is missing.`,\n });\n }\n}\n\nfunction recommendField(obj: Record<string, unknown>, field: string, issues: ValidationIssue[]) {\n if (obj[field] === undefined || obj[field] === null || obj[field] === '') {\n issues.push({\n severity: 'warning',\n field,\n message: `Recommended field \"${field}\" is missing.`,\n });\n }\n}\n\nfunction validateArticle(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'headline', issues);\n requireField(schema, 'author', issues);\n requireField(schema, 'datePublished', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'dateModified', issues);\n recommendField(schema, 'publisher', issues);\n recommendField(schema, 'mainEntityOfPage', issues);\n\n if (typeof schema.headline === 'string' && schema.headline.length > 110) {\n issues.push({\n severity: 'warning',\n field: 'headline',\n message: 'Headline should be under 110 characters for Google Rich Results.',\n });\n }\n}\n\nfunction validateProduct(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'offers', issues);\n recommendField(schema, 'aggregateRating', issues);\n recommendField(schema, 'brand', issues);\n recommendField(schema, 'sku', issues);\n}\n\nfunction validateFAQPage(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n const mainEntity = schema.mainEntity as Array<Record<string, unknown>> | undefined;\n if (!mainEntity || !Array.isArray(mainEntity) || mainEntity.length === 0) {\n issues.push({\n severity: 'error',\n field: 'mainEntity',\n message: 'FAQPage requires at least one Question in mainEntity.',\n });\n return;\n }\n\n for (let i = 0; i < mainEntity.length; i++) {\n const q = mainEntity[i]!;\n if (!q.name) {\n issues.push({\n severity: 'error',\n field: `mainEntity[${i}].name`,\n message: `Question ${i + 1} is missing \"name\" (the question text).`,\n });\n }\n const answer = q.acceptedAnswer as Record<string, unknown> | undefined;\n if (!answer?.text) {\n issues.push({\n severity: 'error',\n field: `mainEntity[${i}].acceptedAnswer.text`,\n message: `Question ${i + 1} is missing an answer text.`,\n });\n }\n }\n}\n\nfunction validateBreadcrumbList(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n const items = schema.itemListElement as Array<Record<string, unknown>> | undefined;\n if (!items || !Array.isArray(items) || items.length === 0) {\n issues.push({\n severity: 'error',\n field: 'itemListElement',\n message: 'BreadcrumbList requires at least one ListItem.',\n });\n }\n}\n\nfunction validateEvent(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'startDate', issues);\n requireField(schema, 'location', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'offers', issues);\n recommendField(schema, 'organizer', issues);\n}\n\nfunction validateRecipe(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'image', issues);\n requireField(schema, 'recipeIngredient', issues);\n requireField(schema, 'recipeInstructions', issues);\n recommendField(schema, 'author', issues);\n recommendField(schema, 'datePublished', issues);\n recommendField(schema, 'description', issues);\n recommendField(schema, 'prepTime', issues);\n recommendField(schema, 'totalTime', issues);\n}\n\nfunction validateVideoObject(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'description', issues);\n requireField(schema, 'thumbnailUrl', issues);\n requireField(schema, 'uploadDate', issues);\n recommendField(schema, 'contentUrl', issues);\n recommendField(schema, 'duration', issues);\n}\n\nfunction validateJobPosting(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'title', issues);\n requireField(schema, 'description', issues);\n requireField(schema, 'datePosted', issues);\n requireField(schema, 'hiringOrganization', issues);\n recommendField(schema, 'validThrough', issues);\n recommendField(schema, 'employmentType', issues);\n recommendField(schema, 'baseSalary', issues);\n}\n\nfunction validateLocalBusiness(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'address', issues);\n recommendField(schema, 'telephone', issues);\n recommendField(schema, 'openingHoursSpecification', issues);\n recommendField(schema, 'image', issues);\n recommendField(schema, 'url', issues);\n recommendField(schema, 'geo', issues);\n}\n\nfunction validateCourse(schema: Record<string, unknown>, issues: ValidationIssue[]) {\n requireField(schema, 'name', issues);\n requireField(schema, 'description', issues);\n recommendField(schema, 'provider', issues);\n recommendField(schema, 'offers', issues);\n}\n"],"mappings":"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","names":[]} |
+107
-43
@@ -1,6 +0,48 @@ | ||
| 'use strict'; | ||
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var react = require('react'); | ||
| // src/react.ts | ||
| var react_exports = {}; | ||
| __export(react_exports, { | ||
| ArticleJsonLd: () => ArticleJsonLd, | ||
| BlogPostingJsonLd: () => BlogPostingJsonLd, | ||
| BrandJsonLd: () => BrandJsonLd, | ||
| BreadcrumbJsonLd: () => BreadcrumbJsonLd, | ||
| CourseJsonLd: () => CourseJsonLd, | ||
| EventJsonLd: () => EventJsonLd, | ||
| FAQJsonLd: () => FAQJsonLd, | ||
| HowToJsonLd: () => HowToJsonLd, | ||
| ItemListJsonLd: () => ItemListJsonLd, | ||
| JobPostingJsonLd: () => JobPostingJsonLd, | ||
| JsonLd: () => JsonLd, | ||
| LocalBusinessJsonLd: () => LocalBusinessJsonLd, | ||
| NewsArticleJsonLd: () => NewsArticleJsonLd, | ||
| OrganizationJsonLd: () => OrganizationJsonLd, | ||
| PersonJsonLd: () => PersonJsonLd, | ||
| ProductJsonLd: () => ProductJsonLd, | ||
| RecipeJsonLd: () => RecipeJsonLd, | ||
| ReviewJsonLd: () => ReviewJsonLd, | ||
| ServiceJsonLd: () => ServiceJsonLd, | ||
| SoftwareAppJsonLd: () => SoftwareAppJsonLd, | ||
| VideoJsonLd: () => VideoJsonLd, | ||
| WebSiteJsonLd: () => WebSiteJsonLd | ||
| }); | ||
| module.exports = __toCommonJS(react_exports); | ||
| var import_react = require("react"); | ||
@@ -65,2 +107,5 @@ // src/builders.ts | ||
| } | ||
| function person(props) { | ||
| return withContext(clean({ "@type": "Person", ...props })); | ||
| } | ||
| function event(props) { | ||
@@ -92,2 +137,5 @@ const { type = "Event", ...rest } = props; | ||
| } | ||
| function itemList(props) { | ||
| return withContext(clean({ "@type": "ItemList", ...props })); | ||
| } | ||
| function review(props) { | ||
@@ -99,6 +147,9 @@ return withContext(clean({ "@type": "Review", ...props })); | ||
| } | ||
| function brand(props) { | ||
| return withContext(clean({ "@type": "Brand", ...props })); | ||
| } | ||
| // src/react.ts | ||
| function JsonLd({ schema, dataTestId }) { | ||
| return react.createElement("script", { | ||
| return (0, import_react.createElement)("script", { | ||
| type: "application/ld+json", | ||
@@ -112,76 +163,89 @@ dangerouslySetInnerHTML: { | ||
| function ArticleJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: article(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: article(props) }); | ||
| } | ||
| function BlogPostingJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: blogPosting(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: blogPosting(props) }); | ||
| } | ||
| function NewsArticleJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: newsArticle(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: newsArticle(props) }); | ||
| } | ||
| function ProductJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: product(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: product(props) }); | ||
| } | ||
| function FAQJsonLd({ questions }) { | ||
| return react.createElement(JsonLd, { schema: faqPage(questions) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: faqPage(questions) }); | ||
| } | ||
| function BreadcrumbJsonLd({ items }) { | ||
| return react.createElement(JsonLd, { schema: breadcrumbList(items) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: breadcrumbList(items) }); | ||
| } | ||
| function LocalBusinessJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: localBusiness(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: localBusiness(props) }); | ||
| } | ||
| function OrganizationJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: organization(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: organization(props) }); | ||
| } | ||
| function EventJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: event(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: event(props) }); | ||
| } | ||
| function RecipeJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: recipe(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: recipe(props) }); | ||
| } | ||
| function HowToJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: howTo(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: howTo(props) }); | ||
| } | ||
| function VideoJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: videoObject(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: videoObject(props) }); | ||
| } | ||
| function CourseJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: course(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: course(props) }); | ||
| } | ||
| function JobPostingJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: jobPosting(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: jobPosting(props) }); | ||
| } | ||
| function SoftwareAppJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: softwareApp(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: softwareApp(props) }); | ||
| } | ||
| function WebSiteJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: webSite(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: webSite(props) }); | ||
| } | ||
| function ReviewJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: review(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: review(props) }); | ||
| } | ||
| function ServiceJsonLd(props) { | ||
| return react.createElement(JsonLd, { schema: service(props) }); | ||
| return (0, import_react.createElement)(JsonLd, { schema: service(props) }); | ||
| } | ||
| exports.ArticleJsonLd = ArticleJsonLd; | ||
| exports.BlogPostingJsonLd = BlogPostingJsonLd; | ||
| exports.BreadcrumbJsonLd = BreadcrumbJsonLd; | ||
| exports.CourseJsonLd = CourseJsonLd; | ||
| exports.EventJsonLd = EventJsonLd; | ||
| exports.FAQJsonLd = FAQJsonLd; | ||
| exports.HowToJsonLd = HowToJsonLd; | ||
| exports.JobPostingJsonLd = JobPostingJsonLd; | ||
| exports.JsonLd = JsonLd; | ||
| exports.LocalBusinessJsonLd = LocalBusinessJsonLd; | ||
| exports.NewsArticleJsonLd = NewsArticleJsonLd; | ||
| exports.OrganizationJsonLd = OrganizationJsonLd; | ||
| exports.ProductJsonLd = ProductJsonLd; | ||
| exports.RecipeJsonLd = RecipeJsonLd; | ||
| exports.ReviewJsonLd = ReviewJsonLd; | ||
| exports.ServiceJsonLd = ServiceJsonLd; | ||
| exports.SoftwareAppJsonLd = SoftwareAppJsonLd; | ||
| exports.VideoJsonLd = VideoJsonLd; | ||
| exports.WebSiteJsonLd = WebSiteJsonLd; | ||
| //# sourceMappingURL=react.cjs.map | ||
| function PersonJsonLd(props) { | ||
| return (0, import_react.createElement)(JsonLd, { schema: person(props) }); | ||
| } | ||
| function ItemListJsonLd(props) { | ||
| return (0, import_react.createElement)(JsonLd, { schema: itemList(props) }); | ||
| } | ||
| function BrandJsonLd(props) { | ||
| return (0, import_react.createElement)(JsonLd, { schema: brand(props) }); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| ArticleJsonLd, | ||
| BlogPostingJsonLd, | ||
| BrandJsonLd, | ||
| BreadcrumbJsonLd, | ||
| CourseJsonLd, | ||
| EventJsonLd, | ||
| FAQJsonLd, | ||
| HowToJsonLd, | ||
| ItemListJsonLd, | ||
| JobPostingJsonLd, | ||
| JsonLd, | ||
| LocalBusinessJsonLd, | ||
| NewsArticleJsonLd, | ||
| OrganizationJsonLd, | ||
| PersonJsonLd, | ||
| ProductJsonLd, | ||
| RecipeJsonLd, | ||
| ReviewJsonLd, | ||
| ServiceJsonLd, | ||
| SoftwareAppJsonLd, | ||
| VideoJsonLd, | ||
| WebSiteJsonLd | ||
| }); | ||
| //# sourceMappingURL=react.cjs.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/builders.ts","../src/react.ts"],"names":["createElement"],"mappings":"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","file":"react.cjs","sourcesContent":["// ============================================================================\n// @power-seo/schema — JSON-LD Builder Functions\n// ============================================================================\n\nimport type {\n WithContext,\n ArticleSchema,\n ProductSchema,\n FAQPageSchema,\n FAQQuestionSchema,\n BreadcrumbListSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n PersonSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ItemListSchema,\n ReviewSchema,\n ServiceSchema,\n SchemaGraph,\n SchemaObject,\n} from './types.js';\n\nconst CONTEXT = 'https://schema.org' as const;\n\n/** Add @context to a schema object */\nfunction withContext<T extends { '@type': string }>(\n schema: T,\n): WithContext<T & { '@type': string }> {\n return { '@context': CONTEXT, ...schema };\n}\n\n/** Remove undefined values from an object */\nfunction clean<T extends Record<string, unknown>>(obj: T): T {\n const result = {} as Record<string, unknown>;\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result as T;\n}\n\n// --- Builder Functions ---\n\nexport function article(\n props: Omit<ArticleSchema, '@type'> & { type?: ArticleSchema['@type'] },\n): WithContext<ArticleSchema> {\n const { type = 'Article', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as ArticleSchema);\n}\n\nexport function blogPosting(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'BlogPosting' });\n}\n\nexport function newsArticle(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'NewsArticle' });\n}\n\nexport function product(props: Omit<ProductSchema, '@type'>): WithContext<ProductSchema> {\n return withContext(clean({ '@type': 'Product', ...props }) as ProductSchema);\n}\n\nexport function faqPage(\n questions: Array<{ question: string; answer: string }>,\n): WithContext<FAQPageSchema> {\n const mainEntity: FAQQuestionSchema[] = questions.map((q) => ({\n '@type': 'Question' as const,\n name: q.question,\n acceptedAnswer: {\n '@type': 'Answer' as const,\n text: q.answer,\n },\n }));\n\n return withContext({ '@type': 'FAQPage' as const, mainEntity });\n}\n\nexport function breadcrumbList(\n items: Array<{ name: string; url?: string }>,\n): WithContext<BreadcrumbListSchema> {\n return withContext({\n '@type': 'BreadcrumbList' as const,\n itemListElement: items.map((item, index) =>\n clean({\n '@type': 'ListItem' as const,\n position: index + 1,\n name: item.name,\n item: item.url,\n }),\n ),\n });\n}\n\nexport function localBusiness(\n props: Omit<LocalBusinessSchema, '@type'> & { type?: string },\n): WithContext<LocalBusinessSchema> {\n const { type = 'LocalBusiness', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as LocalBusinessSchema);\n}\n\nexport function organization(\n props: Omit<OrganizationSchema, '@type'>,\n): WithContext<OrganizationSchema> {\n return withContext(clean({ '@type': 'Organization', ...props }) as OrganizationSchema);\n}\n\nexport function person(props: Omit<PersonSchema, '@type'>): WithContext<PersonSchema> {\n return withContext(clean({ '@type': 'Person', ...props }) as PersonSchema);\n}\n\nexport function event(\n props: Omit<EventSchema, '@type'> & { type?: EventSchema['@type'] },\n): WithContext<EventSchema> {\n const { type = 'Event', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as EventSchema);\n}\n\nexport function recipe(props: Omit<RecipeSchema, '@type'>): WithContext<RecipeSchema> {\n return withContext(clean({ '@type': 'Recipe', ...props }) as RecipeSchema);\n}\n\nexport function howTo(props: Omit<HowToSchema, '@type'>): WithContext<HowToSchema> {\n return withContext(clean({ '@type': 'HowTo', ...props }) as HowToSchema);\n}\n\nexport function videoObject(\n props: Omit<VideoObjectSchema, '@type'>,\n): WithContext<VideoObjectSchema> {\n return withContext(clean({ '@type': 'VideoObject', ...props }) as VideoObjectSchema);\n}\n\nexport function course(props: Omit<CourseSchema, '@type'>): WithContext<CourseSchema> {\n return withContext(clean({ '@type': 'Course', ...props }) as CourseSchema);\n}\n\nexport function jobPosting(props: Omit<JobPostingSchema, '@type'>): WithContext<JobPostingSchema> {\n return withContext(clean({ '@type': 'JobPosting', ...props }) as JobPostingSchema);\n}\n\nexport function softwareApp(\n props: Omit<SoftwareAppSchema, '@type'> & { type?: SoftwareAppSchema['@type'] },\n): WithContext<SoftwareAppSchema> {\n const { type = 'SoftwareApplication', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as SoftwareAppSchema);\n}\n\nexport function webSite(props: Omit<WebSiteSchema, '@type'>): WithContext<WebSiteSchema> {\n return withContext(clean({ '@type': 'WebSite', ...props }) as WebSiteSchema);\n}\n\nexport function itemList(props: Omit<ItemListSchema, '@type'>): WithContext<ItemListSchema> {\n return withContext(clean({ '@type': 'ItemList', ...props }) as ItemListSchema);\n}\n\nexport function review(props: Omit<ReviewSchema, '@type'>): WithContext<ReviewSchema> {\n return withContext(clean({ '@type': 'Review', ...props }) as ReviewSchema);\n}\n\nexport function service(props: Omit<ServiceSchema, '@type'>): WithContext<ServiceSchema> {\n return withContext(clean({ '@type': 'Service', ...props }) as ServiceSchema);\n}\n\n// --- Schema Graph Builder ---\n\n/**\n * Build a connected schema graph with multiple types.\n *\n * @example\n * ```ts\n * const graph = schemaGraph([\n * { '@type': 'WebSite', name: 'My Site', url: 'https://example.com' },\n * { '@type': 'Organization', name: 'My Org', url: 'https://example.com' },\n * ]);\n * ```\n */\nexport function schemaGraph(schemas: SchemaObject[]): SchemaGraph {\n return {\n '@context': CONTEXT,\n '@graph': schemas,\n };\n}\n\n/**\n * Serialize a schema object to a JSON-LD string.\n */\nexport function toJsonLdString(\n schema: WithContext<SchemaObject> | SchemaGraph,\n pretty = false,\n): string {\n return JSON.stringify(schema, null, pretty ? 2 : undefined);\n}\n","// ============================================================================\n// @power-seo/schema — React Components for JSON-LD\n// ============================================================================\n\nimport { createElement } from 'react';\nimport type {\n ArticleSchema,\n ProductSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ReviewSchema,\n ServiceSchema,\n SchemaGraph,\n WithContext,\n JsonLdBase,\n} from './types.js';\nimport {\n article,\n blogPosting,\n newsArticle,\n product,\n faqPage,\n breadcrumbList,\n localBusiness,\n organization,\n event,\n recipe,\n howTo,\n videoObject,\n course,\n jobPosting,\n softwareApp,\n webSite,\n review,\n service,\n} from './builders.js';\n\n// --- Generic JsonLd Component ---\n\nexport interface JsonLdProps<T extends JsonLdBase = JsonLdBase> {\n schema: WithContext<T> | SchemaGraph;\n /** Use data-testid for testing */\n dataTestId?: string;\n}\n\n/**\n * Render a JSON-LD script tag for any schema type.\n *\n * @example\n * ```tsx\n * <JsonLd schema={article({ headline: 'My Article', ... })} />\n * ```\n */\nexport function JsonLd<T extends JsonLdBase>({ schema, dataTestId }: JsonLdProps<T>) {\n return createElement('script', {\n type: 'application/ld+json',\n dangerouslySetInnerHTML: {\n __html: JSON.stringify(schema),\n },\n 'data-testid': dataTestId,\n });\n}\n\n// --- Pre-built Convenience Components ---\n\ntype OmitType<T> = Omit<T, '@type' | '@context'>;\n\nexport interface ArticleJsonLdProps extends OmitType<ArticleSchema> {\n type?: ArticleSchema['@type'];\n}\n\nexport function ArticleJsonLd(props: ArticleJsonLdProps) {\n return createElement(JsonLd, { schema: article(props) });\n}\n\nexport function BlogPostingJsonLd(props: OmitType<ArticleSchema>) {\n return createElement(JsonLd, { schema: blogPosting(props) });\n}\n\nexport function NewsArticleJsonLd(props: OmitType<ArticleSchema>) {\n return createElement(JsonLd, { schema: newsArticle(props) });\n}\n\nexport function ProductJsonLd(props: OmitType<ProductSchema>) {\n return createElement(JsonLd, { schema: product(props) });\n}\n\nexport interface FAQJsonLdProps {\n questions: Array<{ question: string; answer: string }>;\n}\n\nexport function FAQJsonLd({ questions }: FAQJsonLdProps) {\n return createElement(JsonLd, { schema: faqPage(questions) });\n}\n\nexport interface BreadcrumbJsonLdProps {\n items: Array<{ name: string; url?: string }>;\n}\n\nexport function BreadcrumbJsonLd({ items }: BreadcrumbJsonLdProps) {\n return createElement(JsonLd, { schema: breadcrumbList(items) });\n}\n\nexport interface LocalBusinessJsonLdProps extends OmitType<LocalBusinessSchema> {\n type?: string;\n}\n\nexport function LocalBusinessJsonLd(props: LocalBusinessJsonLdProps) {\n return createElement(JsonLd, { schema: localBusiness(props) });\n}\n\nexport function OrganizationJsonLd(props: OmitType<OrganizationSchema>) {\n return createElement(JsonLd, { schema: organization(props) });\n}\n\nexport interface EventJsonLdProps extends OmitType<EventSchema> {\n type?: EventSchema['@type'];\n}\n\nexport function EventJsonLd(props: EventJsonLdProps) {\n return createElement(JsonLd, { schema: event(props) });\n}\n\nexport function RecipeJsonLd(props: OmitType<RecipeSchema>) {\n return createElement(JsonLd, { schema: recipe(props) });\n}\n\nexport function HowToJsonLd(props: OmitType<HowToSchema>) {\n return createElement(JsonLd, { schema: howTo(props) });\n}\n\nexport function VideoJsonLd(props: OmitType<VideoObjectSchema>) {\n return createElement(JsonLd, { schema: videoObject(props) });\n}\n\nexport function CourseJsonLd(props: OmitType<CourseSchema>) {\n return createElement(JsonLd, { schema: course(props) });\n}\n\nexport function JobPostingJsonLd(props: OmitType<JobPostingSchema>) {\n return createElement(JsonLd, { schema: jobPosting(props) });\n}\n\nexport interface SoftwareAppJsonLdProps extends OmitType<SoftwareAppSchema> {\n type?: SoftwareAppSchema['@type'];\n}\n\nexport function SoftwareAppJsonLd(props: SoftwareAppJsonLdProps) {\n return createElement(JsonLd, { schema: softwareApp(props) });\n}\n\nexport function WebSiteJsonLd(props: OmitType<WebSiteSchema>) {\n return createElement(JsonLd, { schema: webSite(props) });\n}\n\nexport function ReviewJsonLd(props: OmitType<ReviewSchema>) {\n return createElement(JsonLd, { schema: review(props) });\n}\n\nexport function ServiceJsonLd(props: OmitType<ServiceSchema>) {\n return createElement(JsonLd, { schema: service(props) });\n}\n"]} | ||
| {"version":3,"sources":["../src/react.ts","../src/builders.ts"],"sourcesContent":["// @power-seo/schema — React Components for JSON-LD\n// ----------------------------------------------------------------------------\n\nimport { createElement } from 'react';\nimport type {\n ArticleSchema,\n ProductSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n PersonSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ItemListSchema,\n ReviewSchema,\n ServiceSchema,\n BrandSchema,\n SchemaGraph,\n WithContext,\n JsonLdBase,\n} from './types.js';\nimport {\n article,\n blogPosting,\n newsArticle,\n product,\n faqPage,\n breadcrumbList,\n localBusiness,\n organization,\n person,\n event,\n recipe,\n howTo,\n videoObject,\n course,\n jobPosting,\n softwareApp,\n webSite,\n itemList,\n review,\n service,\n brand,\n} from './builders.js';\n\n// --- Generic JsonLd Component ---\n\nexport interface JsonLdProps<T extends JsonLdBase = JsonLdBase> {\n schema: WithContext<T> | SchemaGraph;\n /** Use data-testid for testing */\n dataTestId?: string;\n}\n\n/**\n * Render a JSON-LD script tag for any schema type.\n *\n * @example\n * ```tsx\n * <JsonLd schema={article({ headline: 'My Article', ... })} />\n * ```\n */\nexport function JsonLd<T extends JsonLdBase>({ schema, dataTestId }: JsonLdProps<T>) {\n return createElement('script', {\n type: 'application/ld+json',\n dangerouslySetInnerHTML: {\n __html: JSON.stringify(schema),\n },\n 'data-testid': dataTestId,\n });\n}\n\n// --- Pre-built Convenience Components ---\n\ntype OmitType<T> = Omit<T, '@type' | '@context'>;\n\nexport interface ArticleJsonLdProps extends OmitType<ArticleSchema> {\n type?: ArticleSchema['@type'];\n}\n\nexport function ArticleJsonLd(props: ArticleJsonLdProps) {\n return createElement(JsonLd, { schema: article(props) });\n}\n\nexport function BlogPostingJsonLd(props: OmitType<ArticleSchema>) {\n return createElement(JsonLd, { schema: blogPosting(props) });\n}\n\nexport function NewsArticleJsonLd(props: OmitType<ArticleSchema>) {\n return createElement(JsonLd, { schema: newsArticle(props) });\n}\n\nexport function ProductJsonLd(props: OmitType<ProductSchema>) {\n return createElement(JsonLd, { schema: product(props) });\n}\n\nexport interface FAQJsonLdProps {\n questions: Array<{ question: string; answer: string }>;\n}\n\nexport function FAQJsonLd({ questions }: FAQJsonLdProps) {\n return createElement(JsonLd, { schema: faqPage(questions) });\n}\n\nexport interface BreadcrumbJsonLdProps {\n items: Array<{ name: string; url?: string }>;\n}\n\nexport function BreadcrumbJsonLd({ items }: BreadcrumbJsonLdProps) {\n return createElement(JsonLd, { schema: breadcrumbList(items) });\n}\n\nexport interface LocalBusinessJsonLdProps extends OmitType<LocalBusinessSchema> {\n type?: string;\n}\n\nexport function LocalBusinessJsonLd(props: LocalBusinessJsonLdProps) {\n return createElement(JsonLd, { schema: localBusiness(props) });\n}\n\nexport function OrganizationJsonLd(props: OmitType<OrganizationSchema>) {\n return createElement(JsonLd, { schema: organization(props) });\n}\n\nexport interface EventJsonLdProps extends OmitType<EventSchema> {\n type?: EventSchema['@type'];\n}\n\nexport function EventJsonLd(props: EventJsonLdProps) {\n return createElement(JsonLd, { schema: event(props) });\n}\n\nexport function RecipeJsonLd(props: OmitType<RecipeSchema>) {\n return createElement(JsonLd, { schema: recipe(props) });\n}\n\nexport function HowToJsonLd(props: OmitType<HowToSchema>) {\n return createElement(JsonLd, { schema: howTo(props) });\n}\n\nexport function VideoJsonLd(props: OmitType<VideoObjectSchema>) {\n return createElement(JsonLd, { schema: videoObject(props) });\n}\n\nexport function CourseJsonLd(props: OmitType<CourseSchema>) {\n return createElement(JsonLd, { schema: course(props) });\n}\n\nexport function JobPostingJsonLd(props: OmitType<JobPostingSchema>) {\n return createElement(JsonLd, { schema: jobPosting(props) });\n}\n\nexport interface SoftwareAppJsonLdProps extends OmitType<SoftwareAppSchema> {\n type?: SoftwareAppSchema['@type'];\n}\n\nexport function SoftwareAppJsonLd(props: SoftwareAppJsonLdProps) {\n return createElement(JsonLd, { schema: softwareApp(props) });\n}\n\nexport function WebSiteJsonLd(props: OmitType<WebSiteSchema>) {\n return createElement(JsonLd, { schema: webSite(props) });\n}\n\nexport function ReviewJsonLd(props: OmitType<ReviewSchema>) {\n return createElement(JsonLd, { schema: review(props) });\n}\n\nexport function ServiceJsonLd(props: OmitType<ServiceSchema>) {\n return createElement(JsonLd, { schema: service(props) });\n}\n\nexport function PersonJsonLd(props: OmitType<PersonSchema>) {\n return createElement(JsonLd, { schema: person(props) });\n}\n\nexport function ItemListJsonLd(props: OmitType<ItemListSchema>) {\n return createElement(JsonLd, { schema: itemList(props) });\n}\n\nexport function BrandJsonLd(props: OmitType<BrandSchema>) {\n return createElement(JsonLd, { schema: brand(props) });\n}\n","// @power-seo/schema — JSON-LD Builder Functions\n// ----------------------------------------------------------------------------\n\nimport type {\n WithContext,\n ArticleSchema,\n ProductSchema,\n FAQPageSchema,\n FAQQuestionSchema,\n BreadcrumbListSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n PersonSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ItemListSchema,\n ReviewSchema,\n ServiceSchema,\n BrandSchema,\n SiteNavigationElementSchema,\n ImageObject,\n SchemaGraph,\n SchemaObject,\n} from './types.js';\n\nconst CONTEXT = 'https://schema.org' as const;\n\n/** Add @context to a schema object */\nfunction withContext<T extends { '@type': string }>(\n schema: T,\n): WithContext<T & { '@type': string }> {\n return { '@context': CONTEXT, ...schema };\n}\n\n/** Remove undefined values from an object */\nfunction clean<T extends Record<string, unknown>>(obj: T): T {\n const result = {} as Record<string, unknown>;\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result as T;\n}\n\n// --- Builder Functions ---\n\nexport function article(\n props: Omit<ArticleSchema, '@type'> & { type?: ArticleSchema['@type'] },\n): WithContext<ArticleSchema> {\n const { type = 'Article', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as ArticleSchema);\n}\n\nexport function blogPosting(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'BlogPosting' });\n}\n\nexport function newsArticle(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'NewsArticle' });\n}\n\nexport function product(props: Omit<ProductSchema, '@type'>): WithContext<ProductSchema> {\n return withContext(clean({ '@type': 'Product', ...props }) as ProductSchema);\n}\n\nexport function faqPage(\n questions: Array<{ question: string; answer: string }>,\n): WithContext<FAQPageSchema> {\n const mainEntity: FAQQuestionSchema[] = questions.map((q) => ({\n '@type': 'Question' as const,\n name: q.question,\n acceptedAnswer: {\n '@type': 'Answer' as const,\n text: q.answer,\n },\n }));\n\n return withContext({ '@type': 'FAQPage' as const, mainEntity });\n}\n\nexport function breadcrumbList(\n items: Array<{ name: string; url?: string }>,\n): WithContext<BreadcrumbListSchema> {\n return withContext({\n '@type': 'BreadcrumbList' as const,\n itemListElement: items.map((item, index) =>\n clean({\n '@type': 'ListItem' as const,\n position: index + 1,\n name: item.name,\n item: item.url,\n }),\n ),\n });\n}\n\nexport function localBusiness(\n props: Omit<LocalBusinessSchema, '@type'> & { type?: string },\n): WithContext<LocalBusinessSchema> {\n const { type = 'LocalBusiness', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as LocalBusinessSchema);\n}\n\nexport function organization(\n props: Omit<OrganizationSchema, '@type'>,\n): WithContext<OrganizationSchema> {\n return withContext(clean({ '@type': 'Organization', ...props }) as OrganizationSchema);\n}\n\nexport function person(props: Omit<PersonSchema, '@type'>): WithContext<PersonSchema> {\n return withContext(clean({ '@type': 'Person', ...props }) as PersonSchema);\n}\n\nexport function event(\n props: Omit<EventSchema, '@type'> & { type?: EventSchema['@type'] },\n): WithContext<EventSchema> {\n const { type = 'Event', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as EventSchema);\n}\n\nexport function recipe(props: Omit<RecipeSchema, '@type'>): WithContext<RecipeSchema> {\n return withContext(clean({ '@type': 'Recipe', ...props }) as RecipeSchema);\n}\n\nexport function howTo(props: Omit<HowToSchema, '@type'>): WithContext<HowToSchema> {\n return withContext(clean({ '@type': 'HowTo', ...props }) as HowToSchema);\n}\n\nexport function videoObject(\n props: Omit<VideoObjectSchema, '@type'>,\n): WithContext<VideoObjectSchema> {\n return withContext(clean({ '@type': 'VideoObject', ...props }) as VideoObjectSchema);\n}\n\nexport function course(props: Omit<CourseSchema, '@type'>): WithContext<CourseSchema> {\n return withContext(clean({ '@type': 'Course', ...props }) as CourseSchema);\n}\n\nexport function jobPosting(props: Omit<JobPostingSchema, '@type'>): WithContext<JobPostingSchema> {\n return withContext(clean({ '@type': 'JobPosting', ...props }) as JobPostingSchema);\n}\n\nexport function softwareApp(\n props: Omit<SoftwareAppSchema, '@type'> & { type?: SoftwareAppSchema['@type'] },\n): WithContext<SoftwareAppSchema> {\n const { type = 'SoftwareApplication', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as SoftwareAppSchema);\n}\n\nexport function webSite(props: Omit<WebSiteSchema, '@type'>): WithContext<WebSiteSchema> {\n return withContext(clean({ '@type': 'WebSite', ...props }) as WebSiteSchema);\n}\n\nexport function itemList(props: Omit<ItemListSchema, '@type'>): WithContext<ItemListSchema> {\n return withContext(clean({ '@type': 'ItemList', ...props }) as ItemListSchema);\n}\n\nexport function review(props: Omit<ReviewSchema, '@type'>): WithContext<ReviewSchema> {\n return withContext(clean({ '@type': 'Review', ...props }) as ReviewSchema);\n}\n\nexport function service(props: Omit<ServiceSchema, '@type'>): WithContext<ServiceSchema> {\n return withContext(clean({ '@type': 'Service', ...props }) as ServiceSchema);\n}\n\nexport function brand(props: Omit<BrandSchema, '@type'>): WithContext<BrandSchema> {\n return withContext(clean({ '@type': 'Brand', ...props }) as BrandSchema);\n}\n\nexport function siteNavigationElement(\n props: Omit<SiteNavigationElementSchema, '@type'>,\n): WithContext<SiteNavigationElementSchema> {\n return withContext(\n clean({ '@type': 'SiteNavigationElement', ...props }) as SiteNavigationElementSchema,\n );\n}\n\nexport function imageObject(props: Omit<ImageObject, '@type'>): WithContext<ImageObject> {\n return withContext(clean({ '@type': 'ImageObject', ...props }) as ImageObject);\n}\n\n// --- Schema Graph Builder ---\n\n/**\n * Build a connected schema graph with multiple types.\n *\n * @example\n * ```ts\n * const graph = schemaGraph([\n * { '@type': 'WebSite', name: 'My Site', url: 'https://example.com' },\n * { '@type': 'Organization', name: 'My Org', url: 'https://example.com' },\n * ]);\n * ```\n */\nexport function schemaGraph(schemas: SchemaObject[]): SchemaGraph {\n return {\n '@context': CONTEXT,\n '@graph': schemas,\n };\n}\n\n/**\n * Serialize a schema object to a JSON-LD string safe for use with\n * `dangerouslySetInnerHTML` inside a `<script>` tag.\n *\n * HTML special characters (`<`, `>`, `&`) are escaped to their Unicode\n * escape sequences so that a string value like `\"</script>\"` cannot\n * prematurely close the script tag (XSS vector).\n */\nexport function toJsonLdString(\n schema: WithContext<SchemaObject> | SchemaGraph,\n pretty = false,\n): string {\n return JSON.stringify(schema, null, pretty ? 2 : undefined)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026');\n}\n"],"mappings":"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","names":[]} |
+5
-2
| import * as react from 'react'; | ||
| import { A as ArticleSchema, p as JsonLdBase, W as WithContext, c as SchemaGraph, C as CourseSchema, E as EventSchema, H as HowToSchema, J as JobPostingSchema, L as LocalBusinessSchema, O as OrganizationSchema, a as ProductSchema, R as RecipeSchema, b as ReviewSchema, d as ServiceSchema, e as SoftwareAppSchema, V as VideoObjectSchema, f as WebSiteSchema } from './types-DZpjF5KF.cjs'; | ||
| import { A as ArticleSchema, r as JsonLdBase, W as WithContext, e as SchemaGraph, B as BrandSchema, C as CourseSchema, E as EventSchema, H as HowToSchema, b as ItemListSchema, J as JobPostingSchema, L as LocalBusinessSchema, O as OrganizationSchema, P as PersonSchema, c as ProductSchema, R as RecipeSchema, d as ReviewSchema, f as ServiceSchema, h as SoftwareAppSchema, V as VideoObjectSchema, i as WebSiteSchema } from './types-CGc2j4fj.cjs'; | ||
@@ -67,3 +67,6 @@ interface JsonLdProps<T extends JsonLdBase = JsonLdBase> { | ||
| declare function ServiceJsonLd(props: OmitType<ServiceSchema>): react.FunctionComponentElement<JsonLdProps<JsonLdBase>>; | ||
| declare function PersonJsonLd(props: OmitType<PersonSchema>): react.FunctionComponentElement<JsonLdProps<JsonLdBase>>; | ||
| declare function ItemListJsonLd(props: OmitType<ItemListSchema>): react.FunctionComponentElement<JsonLdProps<JsonLdBase>>; | ||
| declare function BrandJsonLd(props: OmitType<BrandSchema>): react.FunctionComponentElement<JsonLdProps<JsonLdBase>>; | ||
| export { ArticleJsonLd, type ArticleJsonLdProps, BlogPostingJsonLd, BreadcrumbJsonLd, type BreadcrumbJsonLdProps, CourseJsonLd, EventJsonLd, type EventJsonLdProps, FAQJsonLd, type FAQJsonLdProps, HowToJsonLd, JobPostingJsonLd, JsonLd, type JsonLdProps, LocalBusinessJsonLd, type LocalBusinessJsonLdProps, NewsArticleJsonLd, OrganizationJsonLd, ProductJsonLd, RecipeJsonLd, ReviewJsonLd, ServiceJsonLd, SoftwareAppJsonLd, type SoftwareAppJsonLdProps, VideoJsonLd, WebSiteJsonLd }; | ||
| export { ArticleJsonLd, type ArticleJsonLdProps, BlogPostingJsonLd, BrandJsonLd, BreadcrumbJsonLd, type BreadcrumbJsonLdProps, CourseJsonLd, EventJsonLd, type EventJsonLdProps, FAQJsonLd, type FAQJsonLdProps, HowToJsonLd, ItemListJsonLd, JobPostingJsonLd, JsonLd, type JsonLdProps, LocalBusinessJsonLd, type LocalBusinessJsonLdProps, NewsArticleJsonLd, OrganizationJsonLd, PersonJsonLd, ProductJsonLd, RecipeJsonLd, ReviewJsonLd, ServiceJsonLd, SoftwareAppJsonLd, type SoftwareAppJsonLdProps, VideoJsonLd, WebSiteJsonLd }; |
+5
-2
| import * as react from 'react'; | ||
| import { A as ArticleSchema, p as JsonLdBase, W as WithContext, c as SchemaGraph, C as CourseSchema, E as EventSchema, H as HowToSchema, J as JobPostingSchema, L as LocalBusinessSchema, O as OrganizationSchema, a as ProductSchema, R as RecipeSchema, b as ReviewSchema, d as ServiceSchema, e as SoftwareAppSchema, V as VideoObjectSchema, f as WebSiteSchema } from './types-DZpjF5KF.js'; | ||
| import { A as ArticleSchema, r as JsonLdBase, W as WithContext, e as SchemaGraph, B as BrandSchema, C as CourseSchema, E as EventSchema, H as HowToSchema, b as ItemListSchema, J as JobPostingSchema, L as LocalBusinessSchema, O as OrganizationSchema, P as PersonSchema, c as ProductSchema, R as RecipeSchema, d as ReviewSchema, f as ServiceSchema, h as SoftwareAppSchema, V as VideoObjectSchema, i as WebSiteSchema } from './types-CGc2j4fj.js'; | ||
@@ -67,3 +67,6 @@ interface JsonLdProps<T extends JsonLdBase = JsonLdBase> { | ||
| declare function ServiceJsonLd(props: OmitType<ServiceSchema>): react.FunctionComponentElement<JsonLdProps<JsonLdBase>>; | ||
| declare function PersonJsonLd(props: OmitType<PersonSchema>): react.FunctionComponentElement<JsonLdProps<JsonLdBase>>; | ||
| declare function ItemListJsonLd(props: OmitType<ItemListSchema>): react.FunctionComponentElement<JsonLdProps<JsonLdBase>>; | ||
| declare function BrandJsonLd(props: OmitType<BrandSchema>): react.FunctionComponentElement<JsonLdProps<JsonLdBase>>; | ||
| export { ArticleJsonLd, type ArticleJsonLdProps, BlogPostingJsonLd, BreadcrumbJsonLd, type BreadcrumbJsonLdProps, CourseJsonLd, EventJsonLd, type EventJsonLdProps, FAQJsonLd, type FAQJsonLdProps, HowToJsonLd, JobPostingJsonLd, JsonLd, type JsonLdProps, LocalBusinessJsonLd, type LocalBusinessJsonLdProps, NewsArticleJsonLd, OrganizationJsonLd, ProductJsonLd, RecipeJsonLd, ReviewJsonLd, ServiceJsonLd, SoftwareAppJsonLd, type SoftwareAppJsonLdProps, VideoJsonLd, WebSiteJsonLd }; | ||
| export { ArticleJsonLd, type ArticleJsonLdProps, BlogPostingJsonLd, BrandJsonLd, BreadcrumbJsonLd, type BreadcrumbJsonLdProps, CourseJsonLd, EventJsonLd, type EventJsonLdProps, FAQJsonLd, type FAQJsonLdProps, HowToJsonLd, ItemListJsonLd, JobPostingJsonLd, JsonLd, type JsonLdProps, LocalBusinessJsonLd, type LocalBusinessJsonLdProps, NewsArticleJsonLd, OrganizationJsonLd, PersonJsonLd, ProductJsonLd, RecipeJsonLd, ReviewJsonLd, ServiceJsonLd, SoftwareAppJsonLd, type SoftwareAppJsonLdProps, VideoJsonLd, WebSiteJsonLd }; |
+43
-5
@@ -1,4 +0,3 @@ | ||
| import { createElement } from 'react'; | ||
| // src/react.ts | ||
| import { createElement } from "react"; | ||
@@ -63,2 +62,5 @@ // src/builders.ts | ||
| } | ||
| function person(props) { | ||
| return withContext(clean({ "@type": "Person", ...props })); | ||
| } | ||
| function event(props) { | ||
@@ -90,2 +92,5 @@ const { type = "Event", ...rest } = props; | ||
| } | ||
| function itemList(props) { | ||
| return withContext(clean({ "@type": "ItemList", ...props })); | ||
| } | ||
| function review(props) { | ||
@@ -97,2 +102,5 @@ return withContext(clean({ "@type": "Review", ...props })); | ||
| } | ||
| function brand(props) { | ||
| return withContext(clean({ "@type": "Brand", ...props })); | ||
| } | ||
@@ -163,5 +171,35 @@ // src/react.ts | ||
| } | ||
| export { ArticleJsonLd, BlogPostingJsonLd, BreadcrumbJsonLd, CourseJsonLd, EventJsonLd, FAQJsonLd, HowToJsonLd, JobPostingJsonLd, JsonLd, LocalBusinessJsonLd, NewsArticleJsonLd, OrganizationJsonLd, ProductJsonLd, RecipeJsonLd, ReviewJsonLd, ServiceJsonLd, SoftwareAppJsonLd, VideoJsonLd, WebSiteJsonLd }; | ||
| //# sourceMappingURL=react.js.map | ||
| function PersonJsonLd(props) { | ||
| return createElement(JsonLd, { schema: person(props) }); | ||
| } | ||
| function ItemListJsonLd(props) { | ||
| return createElement(JsonLd, { schema: itemList(props) }); | ||
| } | ||
| function BrandJsonLd(props) { | ||
| return createElement(JsonLd, { schema: brand(props) }); | ||
| } | ||
| export { | ||
| ArticleJsonLd, | ||
| BlogPostingJsonLd, | ||
| BrandJsonLd, | ||
| BreadcrumbJsonLd, | ||
| CourseJsonLd, | ||
| EventJsonLd, | ||
| FAQJsonLd, | ||
| HowToJsonLd, | ||
| ItemListJsonLd, | ||
| JobPostingJsonLd, | ||
| JsonLd, | ||
| LocalBusinessJsonLd, | ||
| NewsArticleJsonLd, | ||
| OrganizationJsonLd, | ||
| PersonJsonLd, | ||
| ProductJsonLd, | ||
| RecipeJsonLd, | ||
| ReviewJsonLd, | ||
| ServiceJsonLd, | ||
| SoftwareAppJsonLd, | ||
| VideoJsonLd, | ||
| WebSiteJsonLd | ||
| }; | ||
| //# sourceMappingURL=react.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/builders.ts","../src/react.ts"],"names":[],"mappings":"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","file":"react.js","sourcesContent":["// ============================================================================\n// @power-seo/schema — JSON-LD Builder Functions\n// ============================================================================\n\nimport type {\n WithContext,\n ArticleSchema,\n ProductSchema,\n FAQPageSchema,\n FAQQuestionSchema,\n BreadcrumbListSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n PersonSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ItemListSchema,\n ReviewSchema,\n ServiceSchema,\n SchemaGraph,\n SchemaObject,\n} from './types.js';\n\nconst CONTEXT = 'https://schema.org' as const;\n\n/** Add @context to a schema object */\nfunction withContext<T extends { '@type': string }>(\n schema: T,\n): WithContext<T & { '@type': string }> {\n return { '@context': CONTEXT, ...schema };\n}\n\n/** Remove undefined values from an object */\nfunction clean<T extends Record<string, unknown>>(obj: T): T {\n const result = {} as Record<string, unknown>;\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result as T;\n}\n\n// --- Builder Functions ---\n\nexport function article(\n props: Omit<ArticleSchema, '@type'> & { type?: ArticleSchema['@type'] },\n): WithContext<ArticleSchema> {\n const { type = 'Article', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as ArticleSchema);\n}\n\nexport function blogPosting(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'BlogPosting' });\n}\n\nexport function newsArticle(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'NewsArticle' });\n}\n\nexport function product(props: Omit<ProductSchema, '@type'>): WithContext<ProductSchema> {\n return withContext(clean({ '@type': 'Product', ...props }) as ProductSchema);\n}\n\nexport function faqPage(\n questions: Array<{ question: string; answer: string }>,\n): WithContext<FAQPageSchema> {\n const mainEntity: FAQQuestionSchema[] = questions.map((q) => ({\n '@type': 'Question' as const,\n name: q.question,\n acceptedAnswer: {\n '@type': 'Answer' as const,\n text: q.answer,\n },\n }));\n\n return withContext({ '@type': 'FAQPage' as const, mainEntity });\n}\n\nexport function breadcrumbList(\n items: Array<{ name: string; url?: string }>,\n): WithContext<BreadcrumbListSchema> {\n return withContext({\n '@type': 'BreadcrumbList' as const,\n itemListElement: items.map((item, index) =>\n clean({\n '@type': 'ListItem' as const,\n position: index + 1,\n name: item.name,\n item: item.url,\n }),\n ),\n });\n}\n\nexport function localBusiness(\n props: Omit<LocalBusinessSchema, '@type'> & { type?: string },\n): WithContext<LocalBusinessSchema> {\n const { type = 'LocalBusiness', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as LocalBusinessSchema);\n}\n\nexport function organization(\n props: Omit<OrganizationSchema, '@type'>,\n): WithContext<OrganizationSchema> {\n return withContext(clean({ '@type': 'Organization', ...props }) as OrganizationSchema);\n}\n\nexport function person(props: Omit<PersonSchema, '@type'>): WithContext<PersonSchema> {\n return withContext(clean({ '@type': 'Person', ...props }) as PersonSchema);\n}\n\nexport function event(\n props: Omit<EventSchema, '@type'> & { type?: EventSchema['@type'] },\n): WithContext<EventSchema> {\n const { type = 'Event', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as EventSchema);\n}\n\nexport function recipe(props: Omit<RecipeSchema, '@type'>): WithContext<RecipeSchema> {\n return withContext(clean({ '@type': 'Recipe', ...props }) as RecipeSchema);\n}\n\nexport function howTo(props: Omit<HowToSchema, '@type'>): WithContext<HowToSchema> {\n return withContext(clean({ '@type': 'HowTo', ...props }) as HowToSchema);\n}\n\nexport function videoObject(\n props: Omit<VideoObjectSchema, '@type'>,\n): WithContext<VideoObjectSchema> {\n return withContext(clean({ '@type': 'VideoObject', ...props }) as VideoObjectSchema);\n}\n\nexport function course(props: Omit<CourseSchema, '@type'>): WithContext<CourseSchema> {\n return withContext(clean({ '@type': 'Course', ...props }) as CourseSchema);\n}\n\nexport function jobPosting(props: Omit<JobPostingSchema, '@type'>): WithContext<JobPostingSchema> {\n return withContext(clean({ '@type': 'JobPosting', ...props }) as JobPostingSchema);\n}\n\nexport function softwareApp(\n props: Omit<SoftwareAppSchema, '@type'> & { type?: SoftwareAppSchema['@type'] },\n): WithContext<SoftwareAppSchema> {\n const { type = 'SoftwareApplication', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as SoftwareAppSchema);\n}\n\nexport function webSite(props: Omit<WebSiteSchema, '@type'>): WithContext<WebSiteSchema> {\n return withContext(clean({ '@type': 'WebSite', ...props }) as WebSiteSchema);\n}\n\nexport function itemList(props: Omit<ItemListSchema, '@type'>): WithContext<ItemListSchema> {\n return withContext(clean({ '@type': 'ItemList', ...props }) as ItemListSchema);\n}\n\nexport function review(props: Omit<ReviewSchema, '@type'>): WithContext<ReviewSchema> {\n return withContext(clean({ '@type': 'Review', ...props }) as ReviewSchema);\n}\n\nexport function service(props: Omit<ServiceSchema, '@type'>): WithContext<ServiceSchema> {\n return withContext(clean({ '@type': 'Service', ...props }) as ServiceSchema);\n}\n\n// --- Schema Graph Builder ---\n\n/**\n * Build a connected schema graph with multiple types.\n *\n * @example\n * ```ts\n * const graph = schemaGraph([\n * { '@type': 'WebSite', name: 'My Site', url: 'https://example.com' },\n * { '@type': 'Organization', name: 'My Org', url: 'https://example.com' },\n * ]);\n * ```\n */\nexport function schemaGraph(schemas: SchemaObject[]): SchemaGraph {\n return {\n '@context': CONTEXT,\n '@graph': schemas,\n };\n}\n\n/**\n * Serialize a schema object to a JSON-LD string.\n */\nexport function toJsonLdString(\n schema: WithContext<SchemaObject> | SchemaGraph,\n pretty = false,\n): string {\n return JSON.stringify(schema, null, pretty ? 2 : undefined);\n}\n","// ============================================================================\n// @power-seo/schema — React Components for JSON-LD\n// ============================================================================\n\nimport { createElement } from 'react';\nimport type {\n ArticleSchema,\n ProductSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ReviewSchema,\n ServiceSchema,\n SchemaGraph,\n WithContext,\n JsonLdBase,\n} from './types.js';\nimport {\n article,\n blogPosting,\n newsArticle,\n product,\n faqPage,\n breadcrumbList,\n localBusiness,\n organization,\n event,\n recipe,\n howTo,\n videoObject,\n course,\n jobPosting,\n softwareApp,\n webSite,\n review,\n service,\n} from './builders.js';\n\n// --- Generic JsonLd Component ---\n\nexport interface JsonLdProps<T extends JsonLdBase = JsonLdBase> {\n schema: WithContext<T> | SchemaGraph;\n /** Use data-testid for testing */\n dataTestId?: string;\n}\n\n/**\n * Render a JSON-LD script tag for any schema type.\n *\n * @example\n * ```tsx\n * <JsonLd schema={article({ headline: 'My Article', ... })} />\n * ```\n */\nexport function JsonLd<T extends JsonLdBase>({ schema, dataTestId }: JsonLdProps<T>) {\n return createElement('script', {\n type: 'application/ld+json',\n dangerouslySetInnerHTML: {\n __html: JSON.stringify(schema),\n },\n 'data-testid': dataTestId,\n });\n}\n\n// --- Pre-built Convenience Components ---\n\ntype OmitType<T> = Omit<T, '@type' | '@context'>;\n\nexport interface ArticleJsonLdProps extends OmitType<ArticleSchema> {\n type?: ArticleSchema['@type'];\n}\n\nexport function ArticleJsonLd(props: ArticleJsonLdProps) {\n return createElement(JsonLd, { schema: article(props) });\n}\n\nexport function BlogPostingJsonLd(props: OmitType<ArticleSchema>) {\n return createElement(JsonLd, { schema: blogPosting(props) });\n}\n\nexport function NewsArticleJsonLd(props: OmitType<ArticleSchema>) {\n return createElement(JsonLd, { schema: newsArticle(props) });\n}\n\nexport function ProductJsonLd(props: OmitType<ProductSchema>) {\n return createElement(JsonLd, { schema: product(props) });\n}\n\nexport interface FAQJsonLdProps {\n questions: Array<{ question: string; answer: string }>;\n}\n\nexport function FAQJsonLd({ questions }: FAQJsonLdProps) {\n return createElement(JsonLd, { schema: faqPage(questions) });\n}\n\nexport interface BreadcrumbJsonLdProps {\n items: Array<{ name: string; url?: string }>;\n}\n\nexport function BreadcrumbJsonLd({ items }: BreadcrumbJsonLdProps) {\n return createElement(JsonLd, { schema: breadcrumbList(items) });\n}\n\nexport interface LocalBusinessJsonLdProps extends OmitType<LocalBusinessSchema> {\n type?: string;\n}\n\nexport function LocalBusinessJsonLd(props: LocalBusinessJsonLdProps) {\n return createElement(JsonLd, { schema: localBusiness(props) });\n}\n\nexport function OrganizationJsonLd(props: OmitType<OrganizationSchema>) {\n return createElement(JsonLd, { schema: organization(props) });\n}\n\nexport interface EventJsonLdProps extends OmitType<EventSchema> {\n type?: EventSchema['@type'];\n}\n\nexport function EventJsonLd(props: EventJsonLdProps) {\n return createElement(JsonLd, { schema: event(props) });\n}\n\nexport function RecipeJsonLd(props: OmitType<RecipeSchema>) {\n return createElement(JsonLd, { schema: recipe(props) });\n}\n\nexport function HowToJsonLd(props: OmitType<HowToSchema>) {\n return createElement(JsonLd, { schema: howTo(props) });\n}\n\nexport function VideoJsonLd(props: OmitType<VideoObjectSchema>) {\n return createElement(JsonLd, { schema: videoObject(props) });\n}\n\nexport function CourseJsonLd(props: OmitType<CourseSchema>) {\n return createElement(JsonLd, { schema: course(props) });\n}\n\nexport function JobPostingJsonLd(props: OmitType<JobPostingSchema>) {\n return createElement(JsonLd, { schema: jobPosting(props) });\n}\n\nexport interface SoftwareAppJsonLdProps extends OmitType<SoftwareAppSchema> {\n type?: SoftwareAppSchema['@type'];\n}\n\nexport function SoftwareAppJsonLd(props: SoftwareAppJsonLdProps) {\n return createElement(JsonLd, { schema: softwareApp(props) });\n}\n\nexport function WebSiteJsonLd(props: OmitType<WebSiteSchema>) {\n return createElement(JsonLd, { schema: webSite(props) });\n}\n\nexport function ReviewJsonLd(props: OmitType<ReviewSchema>) {\n return createElement(JsonLd, { schema: review(props) });\n}\n\nexport function ServiceJsonLd(props: OmitType<ServiceSchema>) {\n return createElement(JsonLd, { schema: service(props) });\n}\n"]} | ||
| {"version":3,"sources":["../src/react.ts","../src/builders.ts"],"sourcesContent":["// @power-seo/schema — React Components for JSON-LD\n// ----------------------------------------------------------------------------\n\nimport { createElement } from 'react';\nimport type {\n ArticleSchema,\n ProductSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n PersonSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ItemListSchema,\n ReviewSchema,\n ServiceSchema,\n BrandSchema,\n SchemaGraph,\n WithContext,\n JsonLdBase,\n} from './types.js';\nimport {\n article,\n blogPosting,\n newsArticle,\n product,\n faqPage,\n breadcrumbList,\n localBusiness,\n organization,\n person,\n event,\n recipe,\n howTo,\n videoObject,\n course,\n jobPosting,\n softwareApp,\n webSite,\n itemList,\n review,\n service,\n brand,\n} from './builders.js';\n\n// --- Generic JsonLd Component ---\n\nexport interface JsonLdProps<T extends JsonLdBase = JsonLdBase> {\n schema: WithContext<T> | SchemaGraph;\n /** Use data-testid for testing */\n dataTestId?: string;\n}\n\n/**\n * Render a JSON-LD script tag for any schema type.\n *\n * @example\n * ```tsx\n * <JsonLd schema={article({ headline: 'My Article', ... })} />\n * ```\n */\nexport function JsonLd<T extends JsonLdBase>({ schema, dataTestId }: JsonLdProps<T>) {\n return createElement('script', {\n type: 'application/ld+json',\n dangerouslySetInnerHTML: {\n __html: JSON.stringify(schema),\n },\n 'data-testid': dataTestId,\n });\n}\n\n// --- Pre-built Convenience Components ---\n\ntype OmitType<T> = Omit<T, '@type' | '@context'>;\n\nexport interface ArticleJsonLdProps extends OmitType<ArticleSchema> {\n type?: ArticleSchema['@type'];\n}\n\nexport function ArticleJsonLd(props: ArticleJsonLdProps) {\n return createElement(JsonLd, { schema: article(props) });\n}\n\nexport function BlogPostingJsonLd(props: OmitType<ArticleSchema>) {\n return createElement(JsonLd, { schema: blogPosting(props) });\n}\n\nexport function NewsArticleJsonLd(props: OmitType<ArticleSchema>) {\n return createElement(JsonLd, { schema: newsArticle(props) });\n}\n\nexport function ProductJsonLd(props: OmitType<ProductSchema>) {\n return createElement(JsonLd, { schema: product(props) });\n}\n\nexport interface FAQJsonLdProps {\n questions: Array<{ question: string; answer: string }>;\n}\n\nexport function FAQJsonLd({ questions }: FAQJsonLdProps) {\n return createElement(JsonLd, { schema: faqPage(questions) });\n}\n\nexport interface BreadcrumbJsonLdProps {\n items: Array<{ name: string; url?: string }>;\n}\n\nexport function BreadcrumbJsonLd({ items }: BreadcrumbJsonLdProps) {\n return createElement(JsonLd, { schema: breadcrumbList(items) });\n}\n\nexport interface LocalBusinessJsonLdProps extends OmitType<LocalBusinessSchema> {\n type?: string;\n}\n\nexport function LocalBusinessJsonLd(props: LocalBusinessJsonLdProps) {\n return createElement(JsonLd, { schema: localBusiness(props) });\n}\n\nexport function OrganizationJsonLd(props: OmitType<OrganizationSchema>) {\n return createElement(JsonLd, { schema: organization(props) });\n}\n\nexport interface EventJsonLdProps extends OmitType<EventSchema> {\n type?: EventSchema['@type'];\n}\n\nexport function EventJsonLd(props: EventJsonLdProps) {\n return createElement(JsonLd, { schema: event(props) });\n}\n\nexport function RecipeJsonLd(props: OmitType<RecipeSchema>) {\n return createElement(JsonLd, { schema: recipe(props) });\n}\n\nexport function HowToJsonLd(props: OmitType<HowToSchema>) {\n return createElement(JsonLd, { schema: howTo(props) });\n}\n\nexport function VideoJsonLd(props: OmitType<VideoObjectSchema>) {\n return createElement(JsonLd, { schema: videoObject(props) });\n}\n\nexport function CourseJsonLd(props: OmitType<CourseSchema>) {\n return createElement(JsonLd, { schema: course(props) });\n}\n\nexport function JobPostingJsonLd(props: OmitType<JobPostingSchema>) {\n return createElement(JsonLd, { schema: jobPosting(props) });\n}\n\nexport interface SoftwareAppJsonLdProps extends OmitType<SoftwareAppSchema> {\n type?: SoftwareAppSchema['@type'];\n}\n\nexport function SoftwareAppJsonLd(props: SoftwareAppJsonLdProps) {\n return createElement(JsonLd, { schema: softwareApp(props) });\n}\n\nexport function WebSiteJsonLd(props: OmitType<WebSiteSchema>) {\n return createElement(JsonLd, { schema: webSite(props) });\n}\n\nexport function ReviewJsonLd(props: OmitType<ReviewSchema>) {\n return createElement(JsonLd, { schema: review(props) });\n}\n\nexport function ServiceJsonLd(props: OmitType<ServiceSchema>) {\n return createElement(JsonLd, { schema: service(props) });\n}\n\nexport function PersonJsonLd(props: OmitType<PersonSchema>) {\n return createElement(JsonLd, { schema: person(props) });\n}\n\nexport function ItemListJsonLd(props: OmitType<ItemListSchema>) {\n return createElement(JsonLd, { schema: itemList(props) });\n}\n\nexport function BrandJsonLd(props: OmitType<BrandSchema>) {\n return createElement(JsonLd, { schema: brand(props) });\n}\n","// @power-seo/schema — JSON-LD Builder Functions\n// ----------------------------------------------------------------------------\n\nimport type {\n WithContext,\n ArticleSchema,\n ProductSchema,\n FAQPageSchema,\n FAQQuestionSchema,\n BreadcrumbListSchema,\n LocalBusinessSchema,\n OrganizationSchema,\n PersonSchema,\n EventSchema,\n RecipeSchema,\n HowToSchema,\n VideoObjectSchema,\n CourseSchema,\n JobPostingSchema,\n SoftwareAppSchema,\n WebSiteSchema,\n ItemListSchema,\n ReviewSchema,\n ServiceSchema,\n BrandSchema,\n SiteNavigationElementSchema,\n ImageObject,\n SchemaGraph,\n SchemaObject,\n} from './types.js';\n\nconst CONTEXT = 'https://schema.org' as const;\n\n/** Add @context to a schema object */\nfunction withContext<T extends { '@type': string }>(\n schema: T,\n): WithContext<T & { '@type': string }> {\n return { '@context': CONTEXT, ...schema };\n}\n\n/** Remove undefined values from an object */\nfunction clean<T extends Record<string, unknown>>(obj: T): T {\n const result = {} as Record<string, unknown>;\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result as T;\n}\n\n// --- Builder Functions ---\n\nexport function article(\n props: Omit<ArticleSchema, '@type'> & { type?: ArticleSchema['@type'] },\n): WithContext<ArticleSchema> {\n const { type = 'Article', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as ArticleSchema);\n}\n\nexport function blogPosting(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'BlogPosting' });\n}\n\nexport function newsArticle(props: Omit<ArticleSchema, '@type'>): WithContext<ArticleSchema> {\n return article({ ...props, type: 'NewsArticle' });\n}\n\nexport function product(props: Omit<ProductSchema, '@type'>): WithContext<ProductSchema> {\n return withContext(clean({ '@type': 'Product', ...props }) as ProductSchema);\n}\n\nexport function faqPage(\n questions: Array<{ question: string; answer: string }>,\n): WithContext<FAQPageSchema> {\n const mainEntity: FAQQuestionSchema[] = questions.map((q) => ({\n '@type': 'Question' as const,\n name: q.question,\n acceptedAnswer: {\n '@type': 'Answer' as const,\n text: q.answer,\n },\n }));\n\n return withContext({ '@type': 'FAQPage' as const, mainEntity });\n}\n\nexport function breadcrumbList(\n items: Array<{ name: string; url?: string }>,\n): WithContext<BreadcrumbListSchema> {\n return withContext({\n '@type': 'BreadcrumbList' as const,\n itemListElement: items.map((item, index) =>\n clean({\n '@type': 'ListItem' as const,\n position: index + 1,\n name: item.name,\n item: item.url,\n }),\n ),\n });\n}\n\nexport function localBusiness(\n props: Omit<LocalBusinessSchema, '@type'> & { type?: string },\n): WithContext<LocalBusinessSchema> {\n const { type = 'LocalBusiness', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as LocalBusinessSchema);\n}\n\nexport function organization(\n props: Omit<OrganizationSchema, '@type'>,\n): WithContext<OrganizationSchema> {\n return withContext(clean({ '@type': 'Organization', ...props }) as OrganizationSchema);\n}\n\nexport function person(props: Omit<PersonSchema, '@type'>): WithContext<PersonSchema> {\n return withContext(clean({ '@type': 'Person', ...props }) as PersonSchema);\n}\n\nexport function event(\n props: Omit<EventSchema, '@type'> & { type?: EventSchema['@type'] },\n): WithContext<EventSchema> {\n const { type = 'Event', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as EventSchema);\n}\n\nexport function recipe(props: Omit<RecipeSchema, '@type'>): WithContext<RecipeSchema> {\n return withContext(clean({ '@type': 'Recipe', ...props }) as RecipeSchema);\n}\n\nexport function howTo(props: Omit<HowToSchema, '@type'>): WithContext<HowToSchema> {\n return withContext(clean({ '@type': 'HowTo', ...props }) as HowToSchema);\n}\n\nexport function videoObject(\n props: Omit<VideoObjectSchema, '@type'>,\n): WithContext<VideoObjectSchema> {\n return withContext(clean({ '@type': 'VideoObject', ...props }) as VideoObjectSchema);\n}\n\nexport function course(props: Omit<CourseSchema, '@type'>): WithContext<CourseSchema> {\n return withContext(clean({ '@type': 'Course', ...props }) as CourseSchema);\n}\n\nexport function jobPosting(props: Omit<JobPostingSchema, '@type'>): WithContext<JobPostingSchema> {\n return withContext(clean({ '@type': 'JobPosting', ...props }) as JobPostingSchema);\n}\n\nexport function softwareApp(\n props: Omit<SoftwareAppSchema, '@type'> & { type?: SoftwareAppSchema['@type'] },\n): WithContext<SoftwareAppSchema> {\n const { type = 'SoftwareApplication', ...rest } = props;\n return withContext(clean({ '@type': type, ...rest }) as SoftwareAppSchema);\n}\n\nexport function webSite(props: Omit<WebSiteSchema, '@type'>): WithContext<WebSiteSchema> {\n return withContext(clean({ '@type': 'WebSite', ...props }) as WebSiteSchema);\n}\n\nexport function itemList(props: Omit<ItemListSchema, '@type'>): WithContext<ItemListSchema> {\n return withContext(clean({ '@type': 'ItemList', ...props }) as ItemListSchema);\n}\n\nexport function review(props: Omit<ReviewSchema, '@type'>): WithContext<ReviewSchema> {\n return withContext(clean({ '@type': 'Review', ...props }) as ReviewSchema);\n}\n\nexport function service(props: Omit<ServiceSchema, '@type'>): WithContext<ServiceSchema> {\n return withContext(clean({ '@type': 'Service', ...props }) as ServiceSchema);\n}\n\nexport function brand(props: Omit<BrandSchema, '@type'>): WithContext<BrandSchema> {\n return withContext(clean({ '@type': 'Brand', ...props }) as BrandSchema);\n}\n\nexport function siteNavigationElement(\n props: Omit<SiteNavigationElementSchema, '@type'>,\n): WithContext<SiteNavigationElementSchema> {\n return withContext(\n clean({ '@type': 'SiteNavigationElement', ...props }) as SiteNavigationElementSchema,\n );\n}\n\nexport function imageObject(props: Omit<ImageObject, '@type'>): WithContext<ImageObject> {\n return withContext(clean({ '@type': 'ImageObject', ...props }) as ImageObject);\n}\n\n// --- Schema Graph Builder ---\n\n/**\n * Build a connected schema graph with multiple types.\n *\n * @example\n * ```ts\n * const graph = schemaGraph([\n * { '@type': 'WebSite', name: 'My Site', url: 'https://example.com' },\n * { '@type': 'Organization', name: 'My Org', url: 'https://example.com' },\n * ]);\n * ```\n */\nexport function schemaGraph(schemas: SchemaObject[]): SchemaGraph {\n return {\n '@context': CONTEXT,\n '@graph': schemas,\n };\n}\n\n/**\n * Serialize a schema object to a JSON-LD string safe for use with\n * `dangerouslySetInnerHTML` inside a `<script>` tag.\n *\n * HTML special characters (`<`, `>`, `&`) are escaped to their Unicode\n * escape sequences so that a string value like `\"</script>\"` cannot\n * prematurely close the script tag (XSS vector).\n */\nexport function toJsonLdString(\n schema: WithContext<SchemaObject> | SchemaGraph,\n pretty = false,\n): string {\n return JSON.stringify(schema, null, pretty ? 2 : undefined)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026');\n}\n"],"mappings":"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","names":[]} |
+12
-4
| { | ||
| "name": "@power-seo/schema", | ||
| "version": "1.0.4", | ||
| "description": "Type-safe JSON-LD structured data builder with 25+ schema types and React components", | ||
| "version": "1.0.6", | ||
| "description": "Type-safe JSON-LD structured data builder with 23 schema builders and React components", | ||
| "license": "MIT", | ||
@@ -48,7 +48,7 @@ "type": "module", | ||
| "@testing-library/react": "^16.0.0", | ||
| "@types/react": "^19.0.0", | ||
| "@types/react": "^19.2.14", | ||
| "jsdom": "^25.0.0", | ||
| "react": "^19.0.0", | ||
| "react-dom": "^19.0.0", | ||
| "rimraf": "^6.0.0", | ||
| "rimraf": "^6.1.3", | ||
| "tsup": "^8.3.0", | ||
@@ -74,3 +74,11 @@ "typescript": "^5.7.0", | ||
| "access": "public" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/CyberCraftBD/power-seo/issues" | ||
| }, | ||
| "homepage": "https://github.com/CyberCraftBD/power-seo/tree/main/packages/schema#readme", | ||
| "funding": { | ||
| "type": "github", | ||
| "url": "https://github.com/sponsors/cybercraftbd" | ||
| } | ||
| } |
+344
-256
@@ -1,5 +0,7 @@ | ||
| # @power-seo/schema — Type-Safe JSON-LD Structured Data for React, Next.js & Remix — 20 Builders, 18 Components, Schema Graph | ||
| # @power-seo/schema | ||
| [](https://www.npmjs.com/package/@power-seo/schema) | ||
| [](https://www.npmjs.com/package/@power-seo/schema) | ||
| [](https://socket.dev/npm/package/@power-seo/schema) | ||
| [](https://github.com/CyberCraftBD/power-seo/actions) | ||
| [](https://opensource.org/licenses/MIT) | ||
@@ -9,64 +11,69 @@ [](https://www.typescriptlang.org/) | ||
| --- | ||
| Type-safe JSON-LD structured data for TypeScript and React — 23 schema.org builder functions, 21 React components, schema graph support, and field validation. Works in Next.js, Remix, Node.js, and Edge runtimes. | ||
| ## Overview | ||
| `@power-seo/schema` gives you a fully typed, builder-function API for generating Google-compliant schema.org markup — with compile-time type checking on every schema property, a `validateSchema()` utility that surfaces missing required fields before pages go live, and pre-built React components that render `<script type="application/ld+json">` tags in one line. Combine multiple schemas into a single `@graph` document via `schemaGraph()` so Google parses all of them. All 23 schema types are independently importable and tree-shakeable. | ||
| **@power-seo/schema** is a type-safe JSON-LD structured data library for TypeScript developers and React teams that helps you build Google-compliant schema.org markup — with 20 builder functions, 18 pre-built React components, schema graph support, and field validation. | ||
| > **Zero runtime dependencies** — only `@power-seo/core` as a peer. | ||
| **What it does** | ||
| --- | ||
| - ✅ **20 schema.org type builders** — Article, FAQPage, Product, LocalBusiness, Event, Recipe, HowTo, VideoObject, Course, JobPosting, and more | ||
| - ✅ **18 ready-to-use React components** — `<ArticleJsonLd>`, `<FAQJsonLd>`, `<ProductJsonLd>`, `<BreadcrumbJsonLd>`, and more | ||
| - ✅ **Schema graph** — combine multiple schemas into a single `@graph` document with `schemaGraph()` | ||
| - ✅ **Field validation** — `validateSchema()` checks required fields and returns `{ valid, errors }` without throwing | ||
| - ✅ **Safe serialization** — `toJsonLdString()` for `dangerouslySetInnerHTML` | ||
| ## Why @power-seo/schema? | ||
| **What it is not** | ||
| | | Without | With | | ||
| | ------------------------- | ------------------------------------------------- | -------------------------------------------------------------------------- | | ||
| | Field type safety | ❌ Hand-written JSON, no types | ✅ Typed builder functions catch missing fields at compile time | | ||
| | Multiple schemas per page | ❌ Separate `<script>` tags, Google may miss some | ✅ `schemaGraph()` combines all into one `@graph` document | | ||
| | Field validation | ❌ Silent failures in rich results | ✅ `validateSchema()` returns structured issues before deploy | | ||
| | React rendering | ❌ Manual `dangerouslySetInnerHTML` boilerplate | ✅ `<ArticleJsonLd>` and 20 other components in one import | | ||
| | Schema coverage | ❌ Only Article/FAQ in most packages | ✅ 23 types: Article, Product, FAQ, LocalBusiness, Event, Recipe, and more | | ||
| | Framework support | ❌ WordPress / next-seo only | ✅ Next.js, Remix, Node.js, Edge, static site generators | | ||
| - ❌ **Not a Google Search Console validator** — validates field presence, not full Google Rich Results spec compliance | ||
| - ❌ **Not a scraper** — does not fetch structured data from external pages | ||
| --- | ||
| **Recommended for** | ||
| ## Features | ||
| - **Next.js App Router pages**, **Remix routes**, **React SSR apps**, and **programmatic SEO sites** targeting Google rich results | ||
| - **23 schema.org type builder functions** — Article, BlogPosting, NewsArticle, Product, FAQPage, BreadcrumbList, LocalBusiness, Organization, Person, Event, Recipe, HowTo, VideoObject, Course, JobPosting, SoftwareApplication, WebSite, ItemList, Review, Service, Brand, SiteNavigationElement, ImageObject | ||
| - **21 pre-built React components** — `<ArticleJsonLd>`, `<FAQJsonLd>`, `<ProductJsonLd>`, `<BreadcrumbJsonLd>`, `<LocalBusinessJsonLd>`, `<OrganizationJsonLd>`, `<PersonJsonLd>`, `<EventJsonLd>`, `<RecipeJsonLd>`, `<HowToJsonLd>`, `<VideoJsonLd>`, `<CourseJsonLd>`, `<JobPostingJsonLd>`, `<SoftwareAppJsonLd>`, `<WebSiteJsonLd>`, `<ItemListJsonLd>`, `<ReviewJsonLd>`, `<ServiceJsonLd>`, `<BrandJsonLd>`, `<NewsArticleJsonLd>`, `<BlogPostingJsonLd>` | ||
| - **Generic `<JsonLd>` component** — renders any custom schema object as a JSON-LD script tag | ||
| - **`schemaGraph()`** — combine multiple schemas into a single `@graph` document for optimal Google parsing | ||
| - **`toJsonLdString()`** — serialize any schema object to a safe JSON-LD string for `dangerouslySetInnerHTML` | ||
| - **`validateSchema()`** — validate required fields without throwing; returns `{ valid, issues }` with severity, field, and message per issue | ||
| - **React optional** — all 23 builder functions work without React; components available via `/react` subpath export | ||
| - **Type-safe API** — TypeScript-first with full typed interfaces for every schema type including nested objects | ||
| - **Tree-shakeable** — import only the schema types you use; zero dead code in your bundle | ||
| - **Dual ESM + CJS** — ships both formats via tsup for any bundler or `require()` usage | ||
| --- | ||
| ## Why @power-seo/schema Matters | ||
| ## Comparison | ||
| **The problem** | ||
| | Feature | @power-seo/schema | next-seo | schema-dts | json-ld.js | react-schemaorg | | ||
| | ----------------------------- | :---------------: | :------: | :--------: | :--------: | :-------------: | | ||
| | Typed builder functions | ✅ | Partial | ❌ | ❌ | ❌ | | ||
| | Ready-to-use React components | ✅ | ✅ | ❌ | ❌ | Partial | | ||
| | `@graph` support | ✅ | ❌ | ❌ | ✅ | ❌ | | ||
| | Built-in field validation | ✅ | ❌ | ❌ | ❌ | ❌ | | ||
| | Works without React | ✅ | ❌ | ✅ | ✅ | ❌ | | ||
| | 23 schema types | ✅ | Partial | ✅ | ✅ | ❌ | | ||
| | CI / Node.js usage | ✅ | ❌ | ✅ | ✅ | ❌ | | ||
| | Zero runtime dependencies | ✅ | ❌ | ✅ | ❌ | ❌ | | ||
| | TypeScript-first | ✅ | Partial | ✅ | ❌ | ❌ | | ||
| | Tree-shakeable | ✅ | ❌ | ✅ | ❌ | ❌ | | ||
| - **Hand-written JSON-LD has no type checking** — missing required fields like `datePublished` or `author` silently fail Google Rich Results | ||
| - **Multiple schemas per page need `@graph`** — without it, Google may only process the first schema it finds | ||
| - **Schema types differ** — Article, FAQPage, Product, LocalBusiness each have different required fields and data shapes | ||
| **Why developers care** | ||
| - **SEO:** Rich results (FAQ dropdowns, star ratings, breadcrumb trails) increase SERP real estate and click-through rates | ||
| - **UX:** Rich results improve brand visibility and trust signals in search | ||
| - **Performance:** Server-side serialized JSON-LD adds zero client-side JavaScript overhead | ||
| --- | ||
| ## Key Features | ||
| ## Installation | ||
| - **20 schema.org type builder functions** — Article, BlogPosting, NewsArticle, Product, FAQPage, BreadcrumbList, LocalBusiness, Organization, Person, Event, Recipe, HowTo, VideoObject, Course, JobPosting, SoftwareApplication, WebSite, ItemList, Review, Service | ||
| - **18 pre-built React components** — `<ArticleJsonLd>`, `<FAQJsonLd>`, `<ProductJsonLd>`, `<BreadcrumbJsonLd>`, `<LocalBusinessJsonLd>`, `<EventJsonLd>`, `<RecipeJsonLd>`, `<HowToJsonLd>`, `<VideoJsonLd>`, `<CourseJsonLd>`, `<JobPostingJsonLd>`, `<SoftwareAppJsonLd>`, `<WebSiteJsonLd>`, `<OrganizationJsonLd>`, `<PersonJsonLd>`, `<ItemListJsonLd>`, `<ReviewJsonLd>`, `<NewsArticleJsonLd>` | ||
| - **Generic `<JsonLd>` component** — renders any custom schema object as a JSON-LD script tag | ||
| - **`schemaGraph()`** — combine multiple schemas into a single `@graph` document for optimal Google parsing | ||
| - **`toJsonLdString()`** — serialize any schema object to a safe JSON-LD string | ||
| - **`validateSchema()`** — validate required fields without throwing; returns `{ valid, errors }` | ||
| - **React optional** — builder functions work without React; components available via `/react` subpath export | ||
| - **Type-safe API** — TypeScript-first with full typed interfaces for every schema type including nested objects | ||
| - **Tree-shakeable** — import only the schema types you use | ||
| ```bash | ||
| npm install @power-seo/schema | ||
| ``` | ||
| --- | ||
| ```bash | ||
| yarn add @power-seo/schema | ||
| ``` | ||
| ## Benefits of Using @power-seo/schema | ||
| ```bash | ||
| pnpm add @power-seo/schema | ||
| ``` | ||
| - **Improved rich result eligibility**: Typed builder functions surface missing required fields at compile time | ||
| - **Better SERP visibility**: FAQ dropdowns, product ratings, breadcrumb trails, and job listings in search results | ||
| - **Safer implementation**: `validateSchema()` catches missing fields in CI before pages are published | ||
| - **Faster delivery**: React components render JSON-LD in one line; no hand-coding script tags | ||
| --- | ||
@@ -80,3 +87,3 @@ | ||
| const jsonLd = article({ | ||
| const schema = article({ | ||
| headline: 'My Blog Post', | ||
@@ -90,3 +97,3 @@ description: 'An informative article about SEO.', | ||
| const script = toJsonLdString(jsonLd); | ||
| const script = toJsonLdString(schema); | ||
| // → '{"@context":"https://schema.org","@type":"Article","headline":"My Blog Post",...}' | ||
@@ -109,285 +116,366 @@ ``` | ||
| **What you should see** | ||
| - A `<script type="application/ld+json">` tag in the page `<head>` with valid schema.org JSON | ||
| - `validateSchema(schema).valid === true` for fully populated schemas | ||
| --- | ||
| ## Installation | ||
| ## Usage | ||
| ```bash | ||
| npm i @power-seo/schema | ||
| # or | ||
| yarn add @power-seo/schema | ||
| # or | ||
| pnpm add @power-seo/schema | ||
| # or | ||
| bun add @power-seo/schema | ||
| ``` | ||
| ### Builder Functions (No React Required) | ||
| --- | ||
| Call any builder function with a typed props object to produce a schema-ready JSON-LD object, then pass it to `toJsonLdString()` for serialization or `schemaGraph()` to combine with other schemas. | ||
| ## Framework Compatibility | ||
| ```ts | ||
| import { product, toJsonLdString } from '@power-seo/schema'; | ||
| **Supported** | ||
| const schema = product({ | ||
| name: 'Wireless Headphones', | ||
| description: 'Premium noise-cancelling headphones.', | ||
| image: { url: 'https://example.com/headphones.jpg' }, | ||
| offers: { | ||
| price: 149.99, | ||
| priceCurrency: 'USD', | ||
| availability: 'InStock', | ||
| }, | ||
| aggregateRating: { | ||
| ratingValue: 4.7, | ||
| reviewCount: 312, | ||
| }, | ||
| }); | ||
| - ✅ Next.js App Router — use builder functions in `page.tsx`, pass `toJsonLdString()` to `dangerouslySetInnerHTML` | ||
| - ✅ Next.js Pages Router — use React components or builder functions in `getServerSideProps` | ||
| - ✅ Remix — use builder functions in loaders; render in route components | ||
| - ✅ Node.js 18+ — pure TypeScript, no DOM required for builder functions | ||
| - ✅ Static site generators — generate JSON-LD at build time | ||
| console.log(toJsonLdString(schema)); | ||
| ``` | ||
| **Environment notes** | ||
| ### React Components | ||
| - **SSR/SSG:** Fully supported — JSON-LD is serialized server-side | ||
| - **Edge runtime:** Builder functions and utilities supported; React components require React runtime | ||
| - **Browser-only usage:** Supported for React components; not recommended for builder functions alone | ||
| Import from the `/react` entry point for pre-built JSON-LD components that render `<script type="application/ld+json">` tags: | ||
| --- | ||
| ```tsx | ||
| import { FAQJsonLd, BreadcrumbJsonLd } from '@power-seo/schema/react'; | ||
| ## Use Cases | ||
| function PageHead() { | ||
| return ( | ||
| <> | ||
| <FAQJsonLd | ||
| questions={[ | ||
| { question: 'What is JSON-LD?', answer: 'A structured data format used by Google.' }, | ||
| { question: 'Do I need React?', answer: 'No — builder functions work without React.' }, | ||
| ]} | ||
| /> | ||
| <BreadcrumbJsonLd | ||
| items={[ | ||
| { name: 'Home', url: 'https://example.com' }, | ||
| { name: 'Blog', url: 'https://example.com/blog' }, | ||
| { name: 'My Post' }, | ||
| ]} | ||
| /> | ||
| </> | ||
| ); | ||
| } | ||
| ``` | ||
| - **Blog posts and articles** — Article/BlogPosting schema for Google Discover and Top Stories eligibility | ||
| - **FAQ pages** — FAQPage schema for FAQ dropdown rich results | ||
| - **Product pages** — Product schema with offers and aggregate ratings for product rich results | ||
| - **Local business sites** — LocalBusiness schema for Google Business Panel and Local Pack | ||
| - **Recipe sites** — Recipe schema for rich cards with images, ratings, and cooking time | ||
| - **Job boards** — JobPosting schema for Google for Jobs integration | ||
| - **Event pages** — Event schema for Google Events rich results | ||
| - **Course platforms** — Course schema for education carousels in Google Search | ||
| - **Software landing pages** — SoftwareApplication schema for app details in results | ||
| ### Schema Graph (Multiple Schemas Per Page) | ||
| --- | ||
| Use `schemaGraph()` to combine multiple schema objects into a single `@graph` document. This ensures Google parses all schemas on the page, not just the first `<script>` tag it finds. | ||
| ## Example (Before / After) | ||
| ```ts | ||
| import { | ||
| article, | ||
| breadcrumbList, | ||
| organization, | ||
| schemaGraph, | ||
| toJsonLdString, | ||
| } from '@power-seo/schema'; | ||
| ```text | ||
| Before: | ||
| - Hand-written JSON-LD: missing "datePublished" → Article not eligible for rich results | ||
| - Multiple schemas in separate <script> tags → Google may only parse the first one | ||
| - No TypeScript types → runtime errors when API data shape changes | ||
| const graph = schemaGraph([ | ||
| article({ headline: 'My Post', datePublished: '2026-01-01', author: { name: 'Jane Doe' } }), | ||
| breadcrumbList([ | ||
| { name: 'Home', url: 'https://example.com' }, | ||
| { name: 'Blog', url: 'https://example.com/blog' }, | ||
| { name: 'My Post' }, | ||
| ]), | ||
| organization({ name: 'Acme Corp', url: 'https://example.com' }), | ||
| ]); | ||
| After (@power-seo/schema): | ||
| - article({ headline, datePublished, author }) → TypeScript flags missing required fields | ||
| - schemaGraph([article, breadcrumb, org]) → single @graph document, all schemas parsed | ||
| - validateSchema(schema).errors → ['Article: datePublished is required'] caught in CI | ||
| const script = toJsonLdString(graph); | ||
| // → '{"@context":"https://schema.org","@graph":[{...},{...},{...}]}' | ||
| ``` | ||
| --- | ||
| ### Field Validation | ||
| ## Implementation Best Practices | ||
| `validateSchema()` checks required fields and returns a structured result without throwing. Use it in CI pipelines to catch missing fields before pages are published. | ||
| - **Always use `schemaGraph()`** when rendering multiple schemas on the same page | ||
| - **Validate in CI** with `validateSchema()` — catch missing required fields before deploying | ||
| - **Use `toJsonLdString()` for `dangerouslySetInnerHTML`** — avoids double-encoding issues | ||
| - **Include `publisher` on Article schemas** — required for Google News eligibility | ||
| - **Set `aggregateRating.reviewCount`** on Product schemas — minimum threshold for star display | ||
| ```ts | ||
| import { article, validateSchema } from '@power-seo/schema'; | ||
| --- | ||
| const schema = article({ headline: 'Incomplete Article' }); // missing datePublished, author | ||
| ## Architecture Overview | ||
| const result = validateSchema(schema); | ||
| // result.valid → false | ||
| // result.issues → [ | ||
| // { severity: 'error', field: 'datePublished', message: 'datePublished is required for Article' }, | ||
| // { severity: 'error', field: 'author', message: 'author is required for Article' }, | ||
| // ] | ||
| **Where it runs** | ||
| if (!result.valid) { | ||
| const errors = result.issues.filter((i) => i.severity === 'error'); | ||
| console.error(`${errors.length} validation error(s) found`); | ||
| errors.forEach((i) => console.error(` ✗ [${i.field}] ${i.message}`)); | ||
| process.exit(1); | ||
| } | ||
| ``` | ||
| - **Build-time**: Generate and validate JSON-LD for all static pages; fail CI on validation errors | ||
| - **Runtime**: Builder functions in SSR routes produce JSON-LD for each request | ||
| - **CI/CD**: Run `validateSchema()` across all schema outputs in pull request checks | ||
| ### FAQ and Breadcrumb Builder Signatures | ||
| **Data flow** | ||
| `faqPage()` and `breadcrumbList()` accept plain arrays directly — not a config object wrapper: | ||
| 1. **Input**: Typed config objects (article config, FAQ questions, product offers, etc.) | ||
| 2. **Analysis**: Builder function assembles `@context`, `@type`, and typed properties | ||
| 3. **Output**: JSON-LD object or serialized string embedded in `<script type="application/ld+json">` | ||
| 4. **Action**: Google parses schema, evaluates eligibility for rich results in SERP | ||
| ```ts | ||
| import { faqPage, breadcrumbList } from '@power-seo/schema'; | ||
| --- | ||
| // faqPage takes a plain array of { question, answer } items | ||
| const faq = faqPage([ | ||
| { question: 'What is schema.org?', answer: 'A shared vocabulary for structured data.' }, | ||
| { question: 'Does Google require JSON-LD?', answer: 'JSON-LD is the recommended format.' }, | ||
| ]); | ||
| ## Features Comparison with Popular Packages | ||
| // breadcrumbList takes a plain array of { name, url? } items | ||
| const breadcrumb = breadcrumbList([ | ||
| { name: 'Home', url: 'https://example.com' }, | ||
| { name: 'Products', url: 'https://example.com/products' }, | ||
| { name: 'Headphones' }, | ||
| ]); | ||
| ``` | ||
| | Capability | next-seo | schema-dts | json-ld | @power-seo/schema | | ||
| | ----------------------------- | -----------: | ---------: | ------: | ----------------: | | ||
| | Typed builder functions | ✅ | ❌ | ❌ | ✅ | | ||
| | Ready-to-use React components | ✅ | ❌ | ❌ | ✅ | | ||
| | `@graph` support | ❌ | ❌ | ❌ | ✅ | | ||
| | Built-in field validation | ❌ | ❌ | ❌ | ✅ | | ||
| | Works without React | ❌ | ✅ | ✅ | ✅ | | ||
| | 20+ schema types | ❌ (partial) | ✅ | ✅ | ✅ | | ||
| ### Next.js App Router | ||
| --- | ||
| Use builder functions in `page.tsx` to generate JSON-LD for server-side rendering: | ||
| ## [@power-seo](https://www.npmjs.com/org/power-seo) Ecosystem | ||
| ```tsx | ||
| import { article, toJsonLdString } from '@power-seo/schema'; | ||
| All 17 packages are independently installable — use only what you need. | ||
| export default function BlogPost({ post }: { post: Post }) { | ||
| const schema = article({ | ||
| headline: post.title, | ||
| description: post.excerpt, | ||
| datePublished: post.publishedAt, | ||
| dateModified: post.updatedAt, | ||
| author: { name: post.author.name, url: post.author.profileUrl }, | ||
| image: { url: post.coverImage, width: 1200, height: 630 }, | ||
| }); | ||
| | Package | Install | Description | | ||
| | ------------------------------------------------------------------------------------------ | ----------------------------------- | -------------------------------------------------------------------------- | | ||
| | [`@power-seo/core`](https://www.npmjs.com/package/@power-seo/core) | `npm i @power-seo/core` | Framework-agnostic utilities, types, validators, and constants | | ||
| | [`@power-seo/react`](https://www.npmjs.com/package/@power-seo/react) | `npm i @power-seo/react` | React SEO components — meta, Open Graph, Twitter Card, robots, breadcrumbs | | ||
| | [`@power-seo/meta`](https://www.npmjs.com/package/@power-seo/meta) | `npm i @power-seo/meta` | SSR meta helpers for Next.js App Router, Remix v2, and generic SSR | | ||
| | [`@power-seo/schema`](https://www.npmjs.com/package/@power-seo/schema) | `npm i @power-seo/schema` | Type-safe JSON-LD structured data — 20 builders + 18 React components | | ||
| | [`@power-seo/content-analysis`](https://www.npmjs.com/package/@power-seo/content-analysis) | `npm i @power-seo/content-analysis` | Yoast-style SEO content scoring engine with React components | | ||
| | [`@power-seo/readability`](https://www.npmjs.com/package/@power-seo/readability) | `npm i @power-seo/readability` | Readability scoring — Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI | | ||
| | [`@power-seo/preview`](https://www.npmjs.com/package/@power-seo/preview) | `npm i @power-seo/preview` | SERP, Open Graph, and Twitter/X Card preview generators | | ||
| | [`@power-seo/sitemap`](https://www.npmjs.com/package/@power-seo/sitemap) | `npm i @power-seo/sitemap` | XML sitemap generation, streaming, index splitting, and validation | | ||
| | [`@power-seo/redirects`](https://www.npmjs.com/package/@power-seo/redirects) | `npm i @power-seo/redirects` | Redirect engine with Next.js, Remix, and Express adapters | | ||
| | [`@power-seo/links`](https://www.npmjs.com/package/@power-seo/links) | `npm i @power-seo/links` | Link graph analysis — orphan detection, suggestions, equity scoring | | ||
| | [`@power-seo/audit`](https://www.npmjs.com/package/@power-seo/audit) | `npm i @power-seo/audit` | Full SEO audit engine — meta, content, structure, performance rules | | ||
| | [`@power-seo/images`](https://www.npmjs.com/package/@power-seo/images) | `npm i @power-seo/images` | Image SEO — alt text, lazy loading, format analysis, image sitemaps | | ||
| | [`@power-seo/ai`](https://www.npmjs.com/package/@power-seo/ai) | `npm i @power-seo/ai` | LLM-agnostic AI prompt templates and parsers for SEO tasks | | ||
| | [`@power-seo/analytics`](https://www.npmjs.com/package/@power-seo/analytics) | `npm i @power-seo/analytics` | Merge GSC + audit data, trend analysis, ranking insights, dashboard | | ||
| | [`@power-seo/search-console`](https://www.npmjs.com/package/@power-seo/search-console) | `npm i @power-seo/search-console` | Google Search Console API — OAuth2, service account, URL inspection | | ||
| | [`@power-seo/integrations`](https://www.npmjs.com/package/@power-seo/integrations) | `npm i @power-seo/integrations` | Semrush and Ahrefs API clients with rate limiting and pagination | | ||
| | [`@power-seo/tracking`](https://www.npmjs.com/package/@power-seo/tracking) | `npm i @power-seo/tracking` | GA4, Clarity, PostHog, Plausible, Fathom — scripts + consent management | | ||
| return ( | ||
| <> | ||
| <script | ||
| type="application/ld+json" | ||
| dangerouslySetInnerHTML={{ __html: toJsonLdString(schema) }} | ||
| /> | ||
| <article>{/* page content */}</article> | ||
| </> | ||
| ); | ||
| } | ||
| ``` | ||
| ### Ecosystem vs alternatives | ||
| > **Security note:** `toJsonLdString()` escapes `<`, `>`, and `&` to their Unicode escape sequences (`\u003c`, `\u003e`, `\u0026`) so a schema string value such as `"</script>"` cannot break out of the surrounding `<script>` tag. This protection is applied automatically — you do not need to sanitize schema field values yourself when using `toJsonLdString()` or the React components. If you write schema JSON manually and inject it with `dangerouslySetInnerHTML`, apply the same escaping or use `toJsonLdString()`. | ||
| | Need | Common approach | @power-seo approach | | ||
| | ----------------------- | -------------------------- | ----------------------------------------- | | ||
| | JSON-LD structured data | `next-seo` (limited types) | `@power-seo/schema` — 20 types + graph | | ||
| | React components | Manual `<script>` tags | `@power-seo/schema/react` — 18 components | | ||
| | Meta tags | `react-helmet` | `@power-seo/react` + `@power-seo/meta` | | ||
| | Sitemap | `next-sitemap` | `@power-seo/sitemap` — streaming + index | | ||
| ### CI Validation Gate | ||
| --- | ||
| Block deploys when schema validation fails: | ||
| ## Enterprise Integration | ||
| ```ts | ||
| import { validateSchema } from '@power-seo/schema'; | ||
| import { allPageSchemas } from './build-schemas'; | ||
| **Multi-tenant SaaS** | ||
| for (const schema of allPageSchemas) { | ||
| const result = validateSchema(schema); | ||
| if (!result.valid) { | ||
| const errors = result.issues.filter((i) => i.severity === 'error'); | ||
| if (errors.length > 0) { | ||
| console.error('Schema validation failed:'); | ||
| errors.forEach((i) => console.error(` ✗ [${i.field}] ${i.message}`)); | ||
| process.exit(1); | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| - **Tenant-aware schemas**: Inject tenant `organization` into every page's `@graph` dynamically | ||
| - **Per-page schema pipelines**: Generate and validate schemas in CI for all content types | ||
| - **Compliance**: `validateSchema()` ensures no rich result opportunities are silently missed | ||
| --- | ||
| **ERP / internal portals** | ||
| ## API Reference | ||
| - Add `Organization` schema to public-facing portals for Knowledge Panel eligibility | ||
| - Use `BreadcrumbList` schema on all navigable public pages | ||
| - Validate schemas as part of the release pipeline | ||
| ### Entry Points | ||
| **Recommended integration pattern** | ||
| | Import | Description | | ||
| | ------------------------- | -------------------------------------------------- | | ||
| | `@power-seo/schema` | Builder functions, utilities, and TypeScript types | | ||
| | `@power-seo/schema/react` | React components for rendering JSON-LD script tags | | ||
| - Run `validateSchema()` in **CI** for all schema objects | ||
| - Fail build on `valid === false` for Article, Product, and FAQ schemas | ||
| - Track rich result status in **Google Search Console** after deployment | ||
| ### Builder Functions | ||
| --- | ||
| | Function | Schema `@type` | Rich Result Eligible | | ||
| | ------------------------------ | ----------------------- | -------------------------- | | ||
| | `article(props)` | `Article` | Yes — Article rich results | | ||
| | `blogPosting(props)` | `BlogPosting` | Yes — Article rich results | | ||
| | `newsArticle(props)` | `NewsArticle` | Yes — Top Stories | | ||
| | `product(props)` | `Product` | Yes — Product rich results | | ||
| | `faqPage(questions)` | `FAQPage` | Yes — FAQ rich results | | ||
| | `breadcrumbList(items)` | `BreadcrumbList` | Yes — Breadcrumbs in SERP | | ||
| | `localBusiness(props)` | `LocalBusiness` | Yes — Local Business panel | | ||
| | `organization(props)` | `Organization` | Yes — Knowledge Panel | | ||
| | `person(props)` | `Person` | Yes — Knowledge Panel | | ||
| | `event(props)` | `Event` | Yes — Event rich results | | ||
| | `recipe(props)` | `Recipe` | Yes — Recipe rich results | | ||
| | `howTo(props)` | `HowTo` | Yes — How-to rich results | | ||
| | `videoObject(props)` | `VideoObject` | Yes — Video rich results | | ||
| | `course(props)` | `Course` | Yes — Course rich results | | ||
| | `jobPosting(props)` | `JobPosting` | Yes — Job Posting results | | ||
| | `softwareApp(props)` | `SoftwareApplication` | Yes — App rich results | | ||
| | `webSite(props)` | `WebSite` | Yes — Sitelinks Searchbox | | ||
| | `itemList(props)` | `ItemList` | Yes — Carousel results | | ||
| | `review(props)` | `Review` | Yes — Review snippet | | ||
| | `service(props)` | `Service` | Partial | | ||
| | `brand(props)` | `Brand` | Partial | | ||
| | `siteNavigationElement(props)` | `SiteNavigationElement` | Partial | | ||
| | `imageObject(props)` | `ImageObject` | Yes — Image rich results | | ||
| ## Scope and Limitations | ||
| ### Utility Functions | ||
| **This package does** | ||
| | Function | Signature | Description | | ||
| | ---------------- | ------------------------------------------------------------------- | --------------------------------------------------- | | ||
| | `toJsonLdString` | `(schema: object, pretty?: boolean) => string` | Serialize schema to safe JSON-LD string | | ||
| | `schemaGraph` | `(schemas: object[]) => object` | Combine schemas into a single `@graph` document | | ||
| | `validateSchema` | `(schema: object) => { valid: boolean; issues: ValidationIssue[] }` | Validate required fields; returns structured issues | | ||
| - ✅ Build typed JSON-LD objects for 20 schema.org types | ||
| - ✅ Render JSON-LD `<script>` tags via 18 React components | ||
| - ✅ Validate required fields and return structured errors | ||
| - ✅ Combine multiple schemas into a single `@graph` document | ||
| ### React Components | ||
| **This package does not** | ||
| Import all components from `@power-seo/schema/react`. | ||
| - ❌ Guarantee Google Rich Results eligibility (Google's spec changes independently) | ||
| - ❌ Fetch schema data from live pages | ||
| - ❌ Submit schemas to Google directly — use Google Search Console for testing | ||
| | Component | Props | Description | | ||
| | ----------------------- | ------------------------------------------------------------ | ---------------------------------- | | ||
| | `<ArticleJsonLd>` | `Omit<ArticleSchema, '@type' \| '@context'>` | Article schema | | ||
| | `<BlogPostingJsonLd>` | `Omit<ArticleSchema, '@type' \| '@context'>` | BlogPosting schema | | ||
| | `<NewsArticleJsonLd>` | `Omit<ArticleSchema, '@type' \| '@context'>` | NewsArticle schema for Top Stories | | ||
| | `<ProductJsonLd>` | `Omit<ProductSchema, '@type' \| '@context'>` | Product with offers and ratings | | ||
| | `<FAQJsonLd>` | `{ questions: Array<{ question: string; answer: string }> }` | FAQPage schema | | ||
| | `<BreadcrumbJsonLd>` | `{ items: Array<{ name: string; url?: string }> }` | BreadcrumbList schema | | ||
| | `<LocalBusinessJsonLd>` | `Omit<LocalBusinessSchema, '@type' \| '@context'>` | LocalBusiness schema | | ||
| | `<OrganizationJsonLd>` | `Omit<OrganizationSchema, '@type' \| '@context'>` | Organization schema | | ||
| | `<PersonJsonLd>` | `Omit<PersonSchema, '@type' \| '@context'>` | Person schema | | ||
| | `<EventJsonLd>` | `Omit<EventSchema, '@type' \| '@context'>` | Event schema | | ||
| | `<RecipeJsonLd>` | `Omit<RecipeSchema, '@type' \| '@context'>` | Recipe schema | | ||
| | `<HowToJsonLd>` | `Omit<HowToSchema, '@type' \| '@context'>` | HowTo schema | | ||
| | `<VideoJsonLd>` | `Omit<VideoObjectSchema, '@type' \| '@context'>` | VideoObject schema | | ||
| | `<CourseJsonLd>` | `Omit<CourseSchema, '@type' \| '@context'>` | Course schema | | ||
| | `<JobPostingJsonLd>` | `Omit<JobPostingSchema, '@type' \| '@context'>` | JobPosting schema | | ||
| | `<SoftwareAppJsonLd>` | `Omit<SoftwareAppSchema, '@type' \| '@context'>` | SoftwareApplication schema | | ||
| | `<WebSiteJsonLd>` | `Omit<WebSiteSchema, '@type' \| '@context'>` | WebSite with SearchAction | | ||
| | `<ItemListJsonLd>` | `Omit<ItemListSchema, '@type' \| '@context'>` | ItemList schema | | ||
| | `<ReviewJsonLd>` | `Omit<ReviewSchema, '@type' \| '@context'>` | Review schema | | ||
| | `<ServiceJsonLd>` | `Omit<ServiceSchema, '@type' \| '@context'>` | Service schema | | ||
| | `<BrandJsonLd>` | `Omit<BrandSchema, '@type' \| '@context'>` | Brand schema | | ||
| | `<JsonLd>` | `{ schema: object }` | Generic — any schema object | | ||
| --- | ||
| ### Types | ||
| ## API Reference | ||
| | Type | Description | | ||
| | ---------------------- | -------------------------------------------------------------------- | | ||
| | `ArticleSchema` | Props for Article, BlogPosting, and NewsArticle builder functions | | ||
| | `ProductSchema` | Props for `product()` builder | | ||
| | `FAQPageSchema` | Output type of `faqPage()` | | ||
| | `BreadcrumbListSchema` | Output type of `breadcrumbList()` | | ||
| | `LocalBusinessSchema` | Props for `localBusiness()` builder | | ||
| | `OrganizationSchema` | Props for `organization()` builder | | ||
| | `PersonSchema` | Props for `person()` builder | | ||
| | `EventSchema` | Props for `event()` builder | | ||
| | `RecipeSchema` | Props for `recipe()` builder | | ||
| | `HowToSchema` | Props for `howTo()` builder | | ||
| | `VideoObjectSchema` | Props for `videoObject()` builder | | ||
| | `CourseSchema` | Props for `course()` builder | | ||
| | `JobPostingSchema` | Props for `jobPosting()` builder | | ||
| | `SoftwareAppSchema` | Props for `softwareApp()` builder | | ||
| | `WebSiteSchema` | Props for `webSite()` builder | | ||
| | `ItemListSchema` | Props for `itemList()` builder | | ||
| | `ReviewSchema` | Props for `review()` builder | | ||
| | `ServiceSchema` | Props for `service()` builder | | ||
| | `BrandSchema` | Props for `brand()` builder | | ||
| | `ValidationIssue` | `{ severity: 'error' \| 'warning'; field: string; message: string }` | | ||
| ### Builder Functions | ||
| --- | ||
| | Function | Schema `@type` | Rich Result Eligible | | ||
| | ----------------------------- | --------------------- | -------------------------- | | ||
| | `article(config)` | `Article` | Yes — Article rich results | | ||
| | `blogPosting(config)` | `BlogPosting` | Yes — Article rich results | | ||
| | `newsArticle(config)` | `NewsArticle` | Yes — Top Stories | | ||
| | `faqPage(config)` | `FAQPage` | Yes — FAQ rich results | | ||
| | `product(config)` | `Product` | Yes — Product rich results | | ||
| | `breadcrumbList(config)` | `BreadcrumbList` | Yes — Breadcrumbs in SERP | | ||
| | `localBusiness(config)` | `LocalBusiness` | Yes — Local Business panel | | ||
| | `organization(config)` | `Organization` | Yes — Knowledge Panel | | ||
| | `person(config)` | `Person` | Yes — Knowledge Panel | | ||
| | `event(config)` | `Event` | Yes — Event rich results | | ||
| | `recipe(config)` | `Recipe` | Yes — Recipe rich results | | ||
| | `howTo(config)` | `HowTo` | Yes — How-to rich results | | ||
| | `videoObject(config)` | `VideoObject` | Yes — Video rich results | | ||
| | `course(config)` | `Course` | Yes — Course rich results | | ||
| | `jobPosting(config)` | `JobPosting` | Yes — Job Posting results | | ||
| | `softwareApplication(config)` | `SoftwareApplication` | Yes — App rich results | | ||
| | `webSite(config)` | `WebSite` | Yes — Sitelinks Searchbox | | ||
| | `itemList(config)` | `ItemList` | Yes — Carousel results | | ||
| | `review(config)` | `Review` | Yes — Review snippet | | ||
| | `service(config)` | `Service` | Partial | | ||
| ## Use Cases | ||
| ### React Components | ||
| - **Blog posts and articles** — Article and BlogPosting schema for Google Discover and Top Stories eligibility | ||
| - **FAQ pages** — FAQPage schema for FAQ accordion rich results in SERPs | ||
| - **Product pages** — Product schema with offers and aggregate ratings for product rich results and star display | ||
| - **Local business sites** — LocalBusiness schema for Google Business Panel and Local Pack | ||
| - **Recipe sites** — Recipe schema for rich cards with images, ratings, and cooking time | ||
| - **Job boards** — JobPosting schema for Google for Jobs integration | ||
| - **Event pages** — Event schema for Google Events rich results | ||
| - **Course platforms** — Course schema for education carousels in Google Search | ||
| - **Software landing pages** — SoftwareApplication schema for app details in results | ||
| - **Multi-schema pages** — `schemaGraph()` to combine Article + Breadcrumb + Organization into a single `@graph` | ||
| - **CI content pipelines** — `validateSchema()` to block deploys when required fields are missing | ||
| | Component | Prop Type | Description | | ||
| | ----------------------- | ----------------------------- | ---------------------------------- | | ||
| | `<ArticleJsonLd>` | `ArticleConfig` | Article / BlogPosting schema | | ||
| | `<NewsArticleJsonLd>` | `NewsArticleConfig` | NewsArticle schema for Top Stories | | ||
| | `<FAQJsonLd>` | `{ questions: FAQItem[] }` | FAQPage schema | | ||
| | `<ProductJsonLd>` | `ProductConfig` | Product with offers and ratings | | ||
| | `<BreadcrumbJsonLd>` | `{ items: BreadcrumbItem[] }` | BreadcrumbList schema | | ||
| | `<LocalBusinessJsonLd>` | `LocalBusinessConfig` | LocalBusiness schema | | ||
| | `<OrganizationJsonLd>` | `OrganizationConfig` | Organization schema | | ||
| | `<PersonJsonLd>` | `PersonConfig` | Person schema | | ||
| | `<EventJsonLd>` | `EventConfig` | Event schema | | ||
| | `<RecipeJsonLd>` | `RecipeConfig` | Recipe schema | | ||
| | `<HowToJsonLd>` | `HowToConfig` | HowTo schema | | ||
| | `<VideoJsonLd>` | `VideoObjectConfig` | VideoObject schema | | ||
| | `<CourseJsonLd>` | `CourseConfig` | Course schema | | ||
| | `<JobPostingJsonLd>` | `JobPostingConfig` | JobPosting schema | | ||
| | `<SoftwareAppJsonLd>` | `SoftwareApplicationConfig` | SoftwareApplication schema | | ||
| | `<WebSiteJsonLd>` | `WebSiteConfig` | WebSite with SearchAction | | ||
| | `<ItemListJsonLd>` | `ItemListConfig` | ItemList schema | | ||
| | `<ReviewJsonLd>` | `ReviewConfig` | Review schema | | ||
| | `<JsonLd>` | `{ schema: object }` | Generic — any schema object | | ||
| --- | ||
| ### Utilities | ||
| ## Architecture Overview | ||
| | Function | Signature | Description | | ||
| | ---------------- | ---------------------------------------------------------- | --------------------------------------- | | ||
| | `toJsonLdString` | `(schema: object) => string` | Serialize schema to safe JSON-LD string | | ||
| | `schemaGraph` | `(schemas: object[]) => object` | Combine schemas into `@graph` document | | ||
| | `validateSchema` | `(schema: object) => { valid: boolean; errors: string[] }` | Validate required fields | | ||
| - **Pure TypeScript** — no compiled binary, no native modules | ||
| - **Zero runtime dependencies** — only `@power-seo/core` as a peer dependency | ||
| - **Framework-agnostic** — builder functions work in any JavaScript environment with no DOM requirement | ||
| - **SSR compatible** — safe to run in Next.js Server Components, Remix loaders, or Express handlers | ||
| - **Edge runtime safe** — no Node.js-specific APIs; builder functions run in Cloudflare Workers, Vercel Edge, Deno | ||
| - **Tree-shakeable** — `"sideEffects": false` with named exports per schema type | ||
| - **Dual ESM + CJS** — ships both formats via tsup for any bundler or `require()` usage | ||
| --- | ||
| ## Contributing | ||
| ## Supply Chain Security | ||
| - Issues: [github.com/cybercraftbd/power-seo/issues](https://github.com/cybercraftbd/power-seo/issues) | ||
| - PRs: [github.com/cybercraftbd/power-seo/pulls](https://github.com/cybercraftbd/power-seo/pulls) | ||
| - Development setup: | ||
| 1. `pnpm i` | ||
| 2. `pnpm build` | ||
| 3. `pnpm test` | ||
| - No install scripts (`postinstall`, `preinstall`) | ||
| - No runtime network access | ||
| - No `eval` or dynamic code execution | ||
| - npm provenance enabled — every release is signed via Sigstore through GitHub Actions | ||
| - CI-signed builds — all releases published via verified `github.com/CyberCraftBD/power-seo` workflow | ||
| - Safe for SSR, Edge, and server environments | ||
| **Release workflow** | ||
| - `npm version patch|minor|major` | ||
| - `npm publish --access public` | ||
| --- | ||
| ## About [CyberCraft Bangladesh](https://ccbd.dev) | ||
| ## The [@power-seo](https://www.npmjs.com/org/power-seo) Ecosystem | ||
| **[CyberCraft Bangladesh](https://ccbd.dev)** is a Bangladesh-based enterprise-grade software engineering company specializing in ERP system development, AI-powered SaaS and business applications, full-stack SEO services, custom website development, and scalable eCommerce platforms. We design and develop intelligent, automation-driven SaaS and enterprise solutions that help startups, SMEs, NGOs, educational institutes, and large organizations streamline operations, enhance digital visibility, and accelerate growth through modern cloud-native technologies. | ||
| All 17 packages are independently installable — use only what you need. | ||
| | | | | ||
| | -------------------- | -------------------------------------------------------------- | | ||
| | **Website** | [ccbd.dev](https://ccbd.dev) | | ||
| | **GitHub** | [github.com/cybercraftbd](https://github.com/cybercraftbd) | | ||
| | **npm Organization** | [npmjs.com/org/power-seo](https://www.npmjs.com/org/power-seo) | | ||
| | **Email** | [info@ccbd.dev](mailto:info@ccbd.dev) | | ||
| | Package | Install | Description | | ||
| | ------------------------------------------------------------------------------------------ | ----------------------------------- | ----------------------------------------------------------------------- | | ||
| | [`@power-seo/core`](https://www.npmjs.com/package/@power-seo/core) | `npm i @power-seo/core` | Framework-agnostic utilities, types, validators, and constants | | ||
| | [`@power-seo/react`](https://www.npmjs.com/package/@power-seo/react) | `npm i @power-seo/react` | React SEO components — meta, Open Graph, Twitter Card, breadcrumbs | | ||
| | [`@power-seo/meta`](https://www.npmjs.com/package/@power-seo/meta) | `npm i @power-seo/meta` | SSR meta helpers for Next.js App Router, Remix v2, and generic SSR | | ||
| | [`@power-seo/schema`](https://www.npmjs.com/package/@power-seo/schema) | `npm i @power-seo/schema` | Type-safe JSON-LD structured data — 23 builders + 21 React components | | ||
| | [`@power-seo/content-analysis`](https://www.npmjs.com/package/@power-seo/content-analysis) | `npm i @power-seo/content-analysis` | Yoast-style SEO content scoring engine with React components | | ||
| | [`@power-seo/readability`](https://www.npmjs.com/package/@power-seo/readability) | `npm i @power-seo/readability` | Readability scoring — Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI | | ||
| | [`@power-seo/preview`](https://www.npmjs.com/package/@power-seo/preview) | `npm i @power-seo/preview` | SERP, Open Graph, and Twitter/X Card preview generators | | ||
| | [`@power-seo/sitemap`](https://www.npmjs.com/package/@power-seo/sitemap) | `npm i @power-seo/sitemap` | XML sitemap generation, streaming, index splitting, and validation | | ||
| | [`@power-seo/redirects`](https://www.npmjs.com/package/@power-seo/redirects) | `npm i @power-seo/redirects` | Redirect engine with Next.js, Remix, and Express adapters | | ||
| | [`@power-seo/links`](https://www.npmjs.com/package/@power-seo/links) | `npm i @power-seo/links` | Link graph analysis — orphan detection, suggestions, equity scoring | | ||
| | [`@power-seo/audit`](https://www.npmjs.com/package/@power-seo/audit) | `npm i @power-seo/audit` | Full SEO audit engine — meta, content, structure, performance rules | | ||
| | [`@power-seo/images`](https://www.npmjs.com/package/@power-seo/images) | `npm i @power-seo/images` | Image SEO — alt text, lazy loading, format analysis, image sitemaps | | ||
| | [`@power-seo/ai`](https://www.npmjs.com/package/@power-seo/ai) | `npm i @power-seo/ai` | LLM-agnostic AI prompt templates and parsers for SEO tasks | | ||
| | [`@power-seo/analytics`](https://www.npmjs.com/package/@power-seo/analytics) | `npm i @power-seo/analytics` | Merge GSC + audit data, trend analysis, ranking insights, dashboard | | ||
| | [`@power-seo/search-console`](https://www.npmjs.com/package/@power-seo/search-console) | `npm i @power-seo/search-console` | Google Search Console API — OAuth2, service account, URL inspection | | ||
| | [`@power-seo/integrations`](https://www.npmjs.com/package/@power-seo/integrations) | `npm i @power-seo/integrations` | Semrush and Ahrefs API clients with rate limiting and pagination | | ||
| | [`@power-seo/tracking`](https://www.npmjs.com/package/@power-seo/tracking) | `npm i @power-seo/tracking` | GA4, Clarity, PostHog, Plausible, Fathom — scripts + consent management | | ||
| --- | ||
| ## License | ||
| ## Keywords | ||
| **MIT** | ||
| json-ld structured data · schema.org typescript · rich results seo · next.js json-ld · react structured data · faq schema · product schema · article schema · breadcrumb schema · local business schema · schema graph · validate schema · seo schema builder · typescript json-ld · nextjs schema · remix seo · job posting schema · event schema · recipe schema · seo rich results · structured data react · schema.org builder · programmatic seo | ||
| --- | ||
| ## Keywords | ||
| ## About [CyberCraft Bangladesh](https://ccbd.dev) | ||
| ```text | ||
| seo, json-ld, structured-data, schema-org, rich-results, typescript, react, nextjs, remix, faq-schema, product-schema, article-schema, local-business, breadcrumb | ||
| ``` | ||
| **[CyberCraft Bangladesh](https://ccbd.dev)** is a Bangladesh-based enterprise-grade software development and Full Stack SEO service provider company specializing in ERP system development, AI-powered SaaS and business applications, full-stack SEO services, custom website development, and scalable eCommerce platforms. We design and develop intelligent, automation-driven SaaS and enterprise solutions that help startups, SMEs, NGOs, educational institutes, and large organizations streamline operations, enhance digital visibility, and accelerate growth through modern cloud-native technologies. | ||
| [](https://ccbd.dev) | ||
| [](https://github.com/cybercraftbd) | ||
| [](https://www.npmjs.com/org/power-seo) | ||
| [](mailto:info@ccbd.dev) | ||
| © 2026 [CyberCraft Bangladesh](https://ccbd.dev) · Released under the [MIT License](../../LICENSE) |
| /** Base type for all JSON-LD objects */ | ||
| interface JsonLdBase { | ||
| '@context'?: 'https://schema.org'; | ||
| '@type': string; | ||
| '@id'?: string; | ||
| } | ||
| /** A thing with a name and URL */ | ||
| interface ThingBase extends JsonLdBase { | ||
| name?: string; | ||
| url?: string; | ||
| description?: string; | ||
| image?: string | ImageObject | Array<string | ImageObject>; | ||
| sameAs?: string | string[]; | ||
| } | ||
| interface ImageObject extends JsonLdBase { | ||
| '@type': 'ImageObject'; | ||
| url: string; | ||
| width?: number | string; | ||
| height?: number | string; | ||
| caption?: string; | ||
| } | ||
| interface PersonSchema extends ThingBase { | ||
| '@type': 'Person'; | ||
| givenName?: string; | ||
| familyName?: string; | ||
| email?: string; | ||
| jobTitle?: string; | ||
| affiliation?: OrganizationSchema; | ||
| } | ||
| interface OrganizationSchema extends ThingBase { | ||
| '@type': 'Organization'; | ||
| logo?: string | ImageObject; | ||
| contactPoint?: ContactPoint | ContactPoint[]; | ||
| address?: PostalAddress; | ||
| foundingDate?: string; | ||
| numberOfEmployees?: number; | ||
| } | ||
| interface ContactPoint extends JsonLdBase { | ||
| '@type': 'ContactPoint'; | ||
| telephone?: string; | ||
| contactType?: string; | ||
| email?: string; | ||
| areaServed?: string | string[]; | ||
| availableLanguage?: string | string[]; | ||
| } | ||
| interface PostalAddress extends JsonLdBase { | ||
| '@type': 'PostalAddress'; | ||
| streetAddress?: string; | ||
| addressLocality?: string; | ||
| addressRegion?: string; | ||
| postalCode?: string; | ||
| addressCountry?: string; | ||
| } | ||
| interface ArticleSchema extends ThingBase { | ||
| '@type': 'Article' | 'BlogPosting' | 'NewsArticle' | 'TechArticle'; | ||
| headline: string; | ||
| author: PersonSchema | PersonSchema[] | OrganizationSchema | string; | ||
| datePublished: string; | ||
| dateModified?: string; | ||
| publisher?: OrganizationSchema; | ||
| mainEntityOfPage?: string | { | ||
| '@type': 'WebPage'; | ||
| '@id': string; | ||
| }; | ||
| articleBody?: string; | ||
| articleSection?: string; | ||
| wordCount?: number; | ||
| keywords?: string | string[]; | ||
| thumbnailUrl?: string; | ||
| } | ||
| interface ProductSchema extends ThingBase { | ||
| '@type': 'Product'; | ||
| brand?: OrganizationSchema | { | ||
| '@type': 'Brand'; | ||
| name: string; | ||
| }; | ||
| sku?: string; | ||
| gtin?: string; | ||
| gtin8?: string; | ||
| gtin13?: string; | ||
| gtin14?: string; | ||
| mpn?: string; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| review?: ReviewSchema | ReviewSchema[]; | ||
| color?: string; | ||
| material?: string; | ||
| } | ||
| interface OfferSchema extends JsonLdBase { | ||
| '@type': 'Offer' | 'AggregateOffer'; | ||
| price: number | string; | ||
| priceCurrency: string; | ||
| availability?: 'https://schema.org/InStock' | 'https://schema.org/OutOfStock' | 'https://schema.org/PreOrder' | 'https://schema.org/Discontinued' | string; | ||
| priceValidUntil?: string; | ||
| url?: string; | ||
| seller?: OrganizationSchema; | ||
| itemCondition?: string; | ||
| lowPrice?: number | string; | ||
| highPrice?: number | string; | ||
| offerCount?: number; | ||
| } | ||
| interface AggregateRatingSchema extends JsonLdBase { | ||
| '@type': 'AggregateRating'; | ||
| ratingValue: number | string; | ||
| reviewCount?: number; | ||
| ratingCount?: number; | ||
| bestRating?: number | string; | ||
| worstRating?: number | string; | ||
| } | ||
| interface ReviewSchema extends JsonLdBase { | ||
| '@type': 'Review'; | ||
| author: PersonSchema | string; | ||
| reviewRating?: RatingSchema; | ||
| reviewBody?: string; | ||
| datePublished?: string; | ||
| name?: string; | ||
| } | ||
| interface RatingSchema extends JsonLdBase { | ||
| '@type': 'Rating'; | ||
| ratingValue: number | string; | ||
| bestRating?: number | string; | ||
| worstRating?: number | string; | ||
| } | ||
| interface FAQPageSchema extends JsonLdBase { | ||
| '@type': 'FAQPage'; | ||
| mainEntity: FAQQuestionSchema[]; | ||
| } | ||
| interface FAQQuestionSchema extends JsonLdBase { | ||
| '@type': 'Question'; | ||
| name: string; | ||
| acceptedAnswer: { | ||
| '@type': 'Answer'; | ||
| text: string; | ||
| }; | ||
| } | ||
| interface BreadcrumbListSchema extends JsonLdBase { | ||
| '@type': 'BreadcrumbList'; | ||
| itemListElement: BreadcrumbItem[]; | ||
| } | ||
| interface BreadcrumbItem extends JsonLdBase { | ||
| '@type': 'ListItem'; | ||
| position: number; | ||
| name: string; | ||
| item?: string; | ||
| } | ||
| interface LocalBusinessSchema extends ThingBase { | ||
| '@type': 'LocalBusiness' | 'Restaurant' | 'Store' | 'MedicalBusiness' | string; | ||
| address: PostalAddress; | ||
| telephone?: string; | ||
| openingHoursSpecification?: OpeningHours | OpeningHours[]; | ||
| geo?: GeoCoordinates; | ||
| priceRange?: string; | ||
| servesCuisine?: string | string[]; | ||
| menu?: string; | ||
| hasMap?: string; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| review?: ReviewSchema | ReviewSchema[]; | ||
| } | ||
| interface OpeningHours extends JsonLdBase { | ||
| '@type': 'OpeningHoursSpecification'; | ||
| dayOfWeek: string | string[]; | ||
| opens: string; | ||
| closes: string; | ||
| } | ||
| interface GeoCoordinates extends JsonLdBase { | ||
| '@type': 'GeoCoordinates'; | ||
| latitude: number; | ||
| longitude: number; | ||
| } | ||
| interface EventSchema extends ThingBase { | ||
| '@type': 'Event' | 'MusicEvent' | 'BusinessEvent' | 'EducationEvent' | string; | ||
| startDate: string; | ||
| endDate?: string; | ||
| location: string | PostalAddress | { | ||
| '@type': 'VirtualLocation'; | ||
| url: string; | ||
| }; | ||
| organizer?: PersonSchema | OrganizationSchema; | ||
| performer?: PersonSchema | PersonSchema[]; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| eventStatus?: string; | ||
| eventAttendanceMode?: string; | ||
| } | ||
| interface RecipeSchema extends ThingBase { | ||
| '@type': 'Recipe'; | ||
| author: PersonSchema | string; | ||
| datePublished?: string; | ||
| prepTime?: string; | ||
| cookTime?: string; | ||
| totalTime?: string; | ||
| recipeYield?: string; | ||
| recipeCategory?: string; | ||
| recipeCuisine?: string; | ||
| recipeIngredient: string[]; | ||
| recipeInstructions: HowToStep[] | string[]; | ||
| nutrition?: NutritionInfo; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| video?: VideoObjectSchema; | ||
| keywords?: string; | ||
| } | ||
| interface NutritionInfo extends JsonLdBase { | ||
| '@type': 'NutritionInformation'; | ||
| calories?: string; | ||
| fatContent?: string; | ||
| carbohydrateContent?: string; | ||
| proteinContent?: string; | ||
| fiberContent?: string; | ||
| sodiumContent?: string; | ||
| sugarContent?: string; | ||
| } | ||
| interface HowToSchema extends ThingBase { | ||
| '@type': 'HowTo'; | ||
| step: HowToStep[]; | ||
| totalTime?: string; | ||
| estimatedCost?: string | MonetaryAmount; | ||
| supply?: HowToSupply[]; | ||
| tool?: HowToTool[]; | ||
| } | ||
| interface HowToStep extends JsonLdBase { | ||
| '@type': 'HowToStep'; | ||
| name?: string; | ||
| text: string; | ||
| url?: string; | ||
| image?: string; | ||
| } | ||
| interface HowToSupply extends JsonLdBase { | ||
| '@type': 'HowToSupply'; | ||
| name: string; | ||
| } | ||
| interface HowToTool extends JsonLdBase { | ||
| '@type': 'HowToTool'; | ||
| name: string; | ||
| } | ||
| interface MonetaryAmount extends JsonLdBase { | ||
| '@type': 'MonetaryAmount'; | ||
| currency: string; | ||
| value: number | string; | ||
| } | ||
| interface VideoObjectSchema extends ThingBase { | ||
| '@type': 'VideoObject'; | ||
| thumbnailUrl: string | string[]; | ||
| uploadDate: string; | ||
| duration?: string; | ||
| contentUrl?: string; | ||
| embedUrl?: string; | ||
| interactionStatistic?: { | ||
| '@type': 'InteractionCounter'; | ||
| interactionType: { | ||
| '@type': 'WatchAction'; | ||
| }; | ||
| userInteractionCount: number; | ||
| }; | ||
| } | ||
| interface CourseSchema extends ThingBase { | ||
| '@type': 'Course'; | ||
| provider?: OrganizationSchema; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| hasCourseInstance?: CourseInstance | CourseInstance[]; | ||
| coursePrerequisites?: string | string[]; | ||
| educationalLevel?: string; | ||
| } | ||
| interface CourseInstance extends JsonLdBase { | ||
| '@type': 'CourseInstance'; | ||
| courseMode?: string; | ||
| instructor?: PersonSchema; | ||
| startDate?: string; | ||
| endDate?: string; | ||
| } | ||
| interface JobPostingSchema extends ThingBase { | ||
| '@type': 'JobPosting'; | ||
| title: string; | ||
| datePosted: string; | ||
| validThrough?: string; | ||
| hiringOrganization: OrganizationSchema; | ||
| jobLocation?: PostalAddress | PostalAddress[]; | ||
| baseSalary?: MonetaryAmount | { | ||
| '@type': 'MonetaryAmount'; | ||
| currency: string; | ||
| value: { | ||
| '@type': 'QuantitativeValue'; | ||
| value?: number; | ||
| minValue?: number; | ||
| maxValue?: number; | ||
| unitText?: string; | ||
| }; | ||
| }; | ||
| employmentType?: string | string[]; | ||
| jobLocationType?: string; | ||
| applicantLocationRequirements?: { | ||
| '@type': 'Country'; | ||
| name: string; | ||
| } | Array<{ | ||
| '@type': 'Country'; | ||
| name: string; | ||
| }>; | ||
| } | ||
| interface SoftwareAppSchema extends ThingBase { | ||
| '@type': 'SoftwareApplication' | 'MobileApplication' | 'WebApplication'; | ||
| applicationCategory?: string; | ||
| operatingSystem?: string; | ||
| offers?: OfferSchema; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| downloadUrl?: string; | ||
| softwareVersion?: string; | ||
| } | ||
| interface WebSiteSchema extends ThingBase { | ||
| '@type': 'WebSite'; | ||
| potentialAction?: SearchActionSchema; | ||
| } | ||
| interface SearchActionSchema extends JsonLdBase { | ||
| '@type': 'SearchAction'; | ||
| target: string | { | ||
| '@type': 'EntryPoint'; | ||
| urlTemplate: string; | ||
| }; | ||
| 'query-input'?: string; | ||
| } | ||
| interface ItemListSchema extends JsonLdBase { | ||
| '@type': 'ItemList'; | ||
| itemListElement: ListItem[]; | ||
| numberOfItems?: number; | ||
| itemListOrder?: 'https://schema.org/ItemListOrderAscending' | 'https://schema.org/ItemListOrderDescending' | 'https://schema.org/ItemListUnordered' | string; | ||
| } | ||
| interface ListItem extends JsonLdBase { | ||
| '@type': 'ListItem'; | ||
| position: number; | ||
| url?: string; | ||
| name?: string; | ||
| item?: ThingBase; | ||
| } | ||
| interface ServiceSchema extends ThingBase { | ||
| '@type': 'Service'; | ||
| provider?: OrganizationSchema | PersonSchema; | ||
| areaServed?: string | string[]; | ||
| serviceType?: string; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| } | ||
| /** Union of all supported schema types */ | ||
| type SchemaObject = ArticleSchema | ProductSchema | FAQPageSchema | BreadcrumbListSchema | LocalBusinessSchema | OrganizationSchema | PersonSchema | EventSchema | RecipeSchema | HowToSchema | VideoObjectSchema | CourseSchema | JobPostingSchema | SoftwareAppSchema | WebSiteSchema | ItemListSchema | ReviewSchema | ServiceSchema; | ||
| /** JSON-LD with context */ | ||
| type WithContext<T extends JsonLdBase> = T & { | ||
| '@context': 'https://schema.org'; | ||
| }; | ||
| /** Schema graph — multiple connected schemas */ | ||
| interface SchemaGraph { | ||
| '@context': 'https://schema.org'; | ||
| '@graph': SchemaObject[]; | ||
| } | ||
| export type { ArticleSchema as A, BreadcrumbListSchema as B, CourseSchema as C, EventSchema as E, FAQPageSchema as F, GeoCoordinates as G, HowToSchema as H, ItemListSchema as I, JobPostingSchema as J, LocalBusinessSchema as L, MonetaryAmount as M, NutritionInfo as N, OrganizationSchema as O, PersonSchema as P, RecipeSchema as R, SchemaObject as S, ThingBase as T, VideoObjectSchema as V, WithContext as W, ProductSchema as a, ReviewSchema as b, SchemaGraph as c, ServiceSchema as d, SoftwareAppSchema as e, WebSiteSchema as f, AggregateRatingSchema as g, BreadcrumbItem as h, ContactPoint as i, CourseInstance as j, FAQQuestionSchema as k, HowToStep as l, HowToSupply as m, HowToTool as n, ImageObject as o, JsonLdBase as p, ListItem as q, OfferSchema as r, OpeningHours as s, PostalAddress as t, RatingSchema as u, SearchActionSchema as v }; |
| /** Base type for all JSON-LD objects */ | ||
| interface JsonLdBase { | ||
| '@context'?: 'https://schema.org'; | ||
| '@type': string; | ||
| '@id'?: string; | ||
| } | ||
| /** A thing with a name and URL */ | ||
| interface ThingBase extends JsonLdBase { | ||
| name?: string; | ||
| url?: string; | ||
| description?: string; | ||
| image?: string | ImageObject | Array<string | ImageObject>; | ||
| sameAs?: string | string[]; | ||
| } | ||
| interface ImageObject extends JsonLdBase { | ||
| '@type': 'ImageObject'; | ||
| url: string; | ||
| width?: number | string; | ||
| height?: number | string; | ||
| caption?: string; | ||
| } | ||
| interface PersonSchema extends ThingBase { | ||
| '@type': 'Person'; | ||
| givenName?: string; | ||
| familyName?: string; | ||
| email?: string; | ||
| jobTitle?: string; | ||
| affiliation?: OrganizationSchema; | ||
| } | ||
| interface OrganizationSchema extends ThingBase { | ||
| '@type': 'Organization'; | ||
| logo?: string | ImageObject; | ||
| contactPoint?: ContactPoint | ContactPoint[]; | ||
| address?: PostalAddress; | ||
| foundingDate?: string; | ||
| numberOfEmployees?: number; | ||
| } | ||
| interface ContactPoint extends JsonLdBase { | ||
| '@type': 'ContactPoint'; | ||
| telephone?: string; | ||
| contactType?: string; | ||
| email?: string; | ||
| areaServed?: string | string[]; | ||
| availableLanguage?: string | string[]; | ||
| } | ||
| interface PostalAddress extends JsonLdBase { | ||
| '@type': 'PostalAddress'; | ||
| streetAddress?: string; | ||
| addressLocality?: string; | ||
| addressRegion?: string; | ||
| postalCode?: string; | ||
| addressCountry?: string; | ||
| } | ||
| interface ArticleSchema extends ThingBase { | ||
| '@type': 'Article' | 'BlogPosting' | 'NewsArticle' | 'TechArticle'; | ||
| headline: string; | ||
| author: PersonSchema | PersonSchema[] | OrganizationSchema | string; | ||
| datePublished: string; | ||
| dateModified?: string; | ||
| publisher?: OrganizationSchema; | ||
| mainEntityOfPage?: string | { | ||
| '@type': 'WebPage'; | ||
| '@id': string; | ||
| }; | ||
| articleBody?: string; | ||
| articleSection?: string; | ||
| wordCount?: number; | ||
| keywords?: string | string[]; | ||
| thumbnailUrl?: string; | ||
| } | ||
| interface ProductSchema extends ThingBase { | ||
| '@type': 'Product'; | ||
| brand?: OrganizationSchema | { | ||
| '@type': 'Brand'; | ||
| name: string; | ||
| }; | ||
| sku?: string; | ||
| gtin?: string; | ||
| gtin8?: string; | ||
| gtin13?: string; | ||
| gtin14?: string; | ||
| mpn?: string; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| review?: ReviewSchema | ReviewSchema[]; | ||
| color?: string; | ||
| material?: string; | ||
| } | ||
| interface OfferSchema extends JsonLdBase { | ||
| '@type': 'Offer' | 'AggregateOffer'; | ||
| price: number | string; | ||
| priceCurrency: string; | ||
| availability?: 'https://schema.org/InStock' | 'https://schema.org/OutOfStock' | 'https://schema.org/PreOrder' | 'https://schema.org/Discontinued' | string; | ||
| priceValidUntil?: string; | ||
| url?: string; | ||
| seller?: OrganizationSchema; | ||
| itemCondition?: string; | ||
| lowPrice?: number | string; | ||
| highPrice?: number | string; | ||
| offerCount?: number; | ||
| } | ||
| interface AggregateRatingSchema extends JsonLdBase { | ||
| '@type': 'AggregateRating'; | ||
| ratingValue: number | string; | ||
| reviewCount?: number; | ||
| ratingCount?: number; | ||
| bestRating?: number | string; | ||
| worstRating?: number | string; | ||
| } | ||
| interface ReviewSchema extends JsonLdBase { | ||
| '@type': 'Review'; | ||
| author: PersonSchema | string; | ||
| reviewRating?: RatingSchema; | ||
| reviewBody?: string; | ||
| datePublished?: string; | ||
| name?: string; | ||
| } | ||
| interface RatingSchema extends JsonLdBase { | ||
| '@type': 'Rating'; | ||
| ratingValue: number | string; | ||
| bestRating?: number | string; | ||
| worstRating?: number | string; | ||
| } | ||
| interface FAQPageSchema extends JsonLdBase { | ||
| '@type': 'FAQPage'; | ||
| mainEntity: FAQQuestionSchema[]; | ||
| } | ||
| interface FAQQuestionSchema extends JsonLdBase { | ||
| '@type': 'Question'; | ||
| name: string; | ||
| acceptedAnswer: { | ||
| '@type': 'Answer'; | ||
| text: string; | ||
| }; | ||
| } | ||
| interface BreadcrumbListSchema extends JsonLdBase { | ||
| '@type': 'BreadcrumbList'; | ||
| itemListElement: BreadcrumbItem[]; | ||
| } | ||
| interface BreadcrumbItem extends JsonLdBase { | ||
| '@type': 'ListItem'; | ||
| position: number; | ||
| name: string; | ||
| item?: string; | ||
| } | ||
| interface LocalBusinessSchema extends ThingBase { | ||
| '@type': 'LocalBusiness' | 'Restaurant' | 'Store' | 'MedicalBusiness' | string; | ||
| address: PostalAddress; | ||
| telephone?: string; | ||
| openingHoursSpecification?: OpeningHours | OpeningHours[]; | ||
| geo?: GeoCoordinates; | ||
| priceRange?: string; | ||
| servesCuisine?: string | string[]; | ||
| menu?: string; | ||
| hasMap?: string; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| review?: ReviewSchema | ReviewSchema[]; | ||
| } | ||
| interface OpeningHours extends JsonLdBase { | ||
| '@type': 'OpeningHoursSpecification'; | ||
| dayOfWeek: string | string[]; | ||
| opens: string; | ||
| closes: string; | ||
| } | ||
| interface GeoCoordinates extends JsonLdBase { | ||
| '@type': 'GeoCoordinates'; | ||
| latitude: number; | ||
| longitude: number; | ||
| } | ||
| interface EventSchema extends ThingBase { | ||
| '@type': 'Event' | 'MusicEvent' | 'BusinessEvent' | 'EducationEvent' | string; | ||
| startDate: string; | ||
| endDate?: string; | ||
| location: string | PostalAddress | { | ||
| '@type': 'VirtualLocation'; | ||
| url: string; | ||
| }; | ||
| organizer?: PersonSchema | OrganizationSchema; | ||
| performer?: PersonSchema | PersonSchema[]; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| eventStatus?: string; | ||
| eventAttendanceMode?: string; | ||
| } | ||
| interface RecipeSchema extends ThingBase { | ||
| '@type': 'Recipe'; | ||
| author: PersonSchema | string; | ||
| datePublished?: string; | ||
| prepTime?: string; | ||
| cookTime?: string; | ||
| totalTime?: string; | ||
| recipeYield?: string; | ||
| recipeCategory?: string; | ||
| recipeCuisine?: string; | ||
| recipeIngredient: string[]; | ||
| recipeInstructions: HowToStep[] | string[]; | ||
| nutrition?: NutritionInfo; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| video?: VideoObjectSchema; | ||
| keywords?: string; | ||
| } | ||
| interface NutritionInfo extends JsonLdBase { | ||
| '@type': 'NutritionInformation'; | ||
| calories?: string; | ||
| fatContent?: string; | ||
| carbohydrateContent?: string; | ||
| proteinContent?: string; | ||
| fiberContent?: string; | ||
| sodiumContent?: string; | ||
| sugarContent?: string; | ||
| } | ||
| interface HowToSchema extends ThingBase { | ||
| '@type': 'HowTo'; | ||
| step: HowToStep[]; | ||
| totalTime?: string; | ||
| estimatedCost?: string | MonetaryAmount; | ||
| supply?: HowToSupply[]; | ||
| tool?: HowToTool[]; | ||
| } | ||
| interface HowToStep extends JsonLdBase { | ||
| '@type': 'HowToStep'; | ||
| name?: string; | ||
| text: string; | ||
| url?: string; | ||
| image?: string; | ||
| } | ||
| interface HowToSupply extends JsonLdBase { | ||
| '@type': 'HowToSupply'; | ||
| name: string; | ||
| } | ||
| interface HowToTool extends JsonLdBase { | ||
| '@type': 'HowToTool'; | ||
| name: string; | ||
| } | ||
| interface MonetaryAmount extends JsonLdBase { | ||
| '@type': 'MonetaryAmount'; | ||
| currency: string; | ||
| value: number | string; | ||
| } | ||
| interface VideoObjectSchema extends ThingBase { | ||
| '@type': 'VideoObject'; | ||
| thumbnailUrl: string | string[]; | ||
| uploadDate: string; | ||
| duration?: string; | ||
| contentUrl?: string; | ||
| embedUrl?: string; | ||
| interactionStatistic?: { | ||
| '@type': 'InteractionCounter'; | ||
| interactionType: { | ||
| '@type': 'WatchAction'; | ||
| }; | ||
| userInteractionCount: number; | ||
| }; | ||
| } | ||
| interface CourseSchema extends ThingBase { | ||
| '@type': 'Course'; | ||
| provider?: OrganizationSchema; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| hasCourseInstance?: CourseInstance | CourseInstance[]; | ||
| coursePrerequisites?: string | string[]; | ||
| educationalLevel?: string; | ||
| } | ||
| interface CourseInstance extends JsonLdBase { | ||
| '@type': 'CourseInstance'; | ||
| courseMode?: string; | ||
| instructor?: PersonSchema; | ||
| startDate?: string; | ||
| endDate?: string; | ||
| } | ||
| interface JobPostingSchema extends ThingBase { | ||
| '@type': 'JobPosting'; | ||
| title: string; | ||
| datePosted: string; | ||
| validThrough?: string; | ||
| hiringOrganization: OrganizationSchema; | ||
| jobLocation?: PostalAddress | PostalAddress[]; | ||
| baseSalary?: MonetaryAmount | { | ||
| '@type': 'MonetaryAmount'; | ||
| currency: string; | ||
| value: { | ||
| '@type': 'QuantitativeValue'; | ||
| value?: number; | ||
| minValue?: number; | ||
| maxValue?: number; | ||
| unitText?: string; | ||
| }; | ||
| }; | ||
| employmentType?: string | string[]; | ||
| jobLocationType?: string; | ||
| applicantLocationRequirements?: { | ||
| '@type': 'Country'; | ||
| name: string; | ||
| } | Array<{ | ||
| '@type': 'Country'; | ||
| name: string; | ||
| }>; | ||
| } | ||
| interface SoftwareAppSchema extends ThingBase { | ||
| '@type': 'SoftwareApplication' | 'MobileApplication' | 'WebApplication'; | ||
| applicationCategory?: string; | ||
| operatingSystem?: string; | ||
| offers?: OfferSchema; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| downloadUrl?: string; | ||
| softwareVersion?: string; | ||
| } | ||
| interface WebSiteSchema extends ThingBase { | ||
| '@type': 'WebSite'; | ||
| potentialAction?: SearchActionSchema; | ||
| } | ||
| interface SearchActionSchema extends JsonLdBase { | ||
| '@type': 'SearchAction'; | ||
| target: string | { | ||
| '@type': 'EntryPoint'; | ||
| urlTemplate: string; | ||
| }; | ||
| 'query-input'?: string; | ||
| } | ||
| interface ItemListSchema extends JsonLdBase { | ||
| '@type': 'ItemList'; | ||
| itemListElement: ListItem[]; | ||
| numberOfItems?: number; | ||
| itemListOrder?: 'https://schema.org/ItemListOrderAscending' | 'https://schema.org/ItemListOrderDescending' | 'https://schema.org/ItemListUnordered' | string; | ||
| } | ||
| interface ListItem extends JsonLdBase { | ||
| '@type': 'ListItem'; | ||
| position: number; | ||
| url?: string; | ||
| name?: string; | ||
| item?: ThingBase; | ||
| } | ||
| interface ServiceSchema extends ThingBase { | ||
| '@type': 'Service'; | ||
| provider?: OrganizationSchema | PersonSchema; | ||
| areaServed?: string | string[]; | ||
| serviceType?: string; | ||
| offers?: OfferSchema | OfferSchema[]; | ||
| aggregateRating?: AggregateRatingSchema; | ||
| } | ||
| /** Union of all supported schema types */ | ||
| type SchemaObject = ArticleSchema | ProductSchema | FAQPageSchema | BreadcrumbListSchema | LocalBusinessSchema | OrganizationSchema | PersonSchema | EventSchema | RecipeSchema | HowToSchema | VideoObjectSchema | CourseSchema | JobPostingSchema | SoftwareAppSchema | WebSiteSchema | ItemListSchema | ReviewSchema | ServiceSchema; | ||
| /** JSON-LD with context */ | ||
| type WithContext<T extends JsonLdBase> = T & { | ||
| '@context': 'https://schema.org'; | ||
| }; | ||
| /** Schema graph — multiple connected schemas */ | ||
| interface SchemaGraph { | ||
| '@context': 'https://schema.org'; | ||
| '@graph': SchemaObject[]; | ||
| } | ||
| export type { ArticleSchema as A, BreadcrumbListSchema as B, CourseSchema as C, EventSchema as E, FAQPageSchema as F, GeoCoordinates as G, HowToSchema as H, ItemListSchema as I, JobPostingSchema as J, LocalBusinessSchema as L, MonetaryAmount as M, NutritionInfo as N, OrganizationSchema as O, PersonSchema as P, RecipeSchema as R, SchemaObject as S, ThingBase as T, VideoObjectSchema as V, WithContext as W, ProductSchema as a, ReviewSchema as b, SchemaGraph as c, ServiceSchema as d, SoftwareAppSchema as e, WebSiteSchema as f, AggregateRatingSchema as g, BreadcrumbItem as h, ContactPoint as i, CourseInstance as j, FAQQuestionSchema as k, HowToStep as l, HowToSupply as m, HowToTool as n, ImageObject as o, JsonLdBase as p, ListItem as q, OfferSchema as r, OpeningHours as s, PostalAddress as t, RatingSchema as u, SearchActionSchema as v }; |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
191102
10.41%1701
18.87%0
-100%0
-100%478
22.56%