sanity-plugin-seofields 1.9.0 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +71 -0
  2. package/dist/{SeoPreview-LMZAWWOE.cjs → SeoPreview-A2XZVMT2.cjs} +4 -4
  3. package/dist/{SeoPreview-LMZAWWOE.cjs.map → SeoPreview-A2XZVMT2.cjs.map} +1 -1
  4. package/dist/{SeoPreview-UNQBKTQO.js → SeoPreview-TATJQFMP.js} +2 -2
  5. package/dist/chunk-CRCXC45D.js +56 -0
  6. package/dist/chunk-CRCXC45D.js.map +1 -0
  7. package/dist/{chunk-HHO2AKAP.js → chunk-DB5MBPRK.js} +13 -13
  8. package/dist/chunk-DB5MBPRK.js.map +1 -0
  9. package/dist/{chunk-3OK3S2F7.cjs → chunk-EUG4MNRC.cjs} +60 -20
  10. package/dist/chunk-EUG4MNRC.cjs.map +1 -0
  11. package/dist/{chunk-Y46ACXM4.cjs → chunk-LHUFL5LS.cjs} +13 -13
  12. package/dist/chunk-LHUFL5LS.cjs.map +1 -0
  13. package/dist/{chunk-Z5AOUU4H.js → chunk-NLEB47UV.js} +60 -20
  14. package/dist/chunk-NLEB47UV.js.map +1 -0
  15. package/dist/{chunk-FUUWBQE2.cjs → chunk-OULUDJPI.cjs} +66 -7
  16. package/dist/chunk-OULUDJPI.cjs.map +1 -0
  17. package/dist/{chunk-KIEO6QG3.js → chunk-XD4HKLEA.js} +66 -7
  18. package/dist/chunk-XD4HKLEA.js.map +1 -0
  19. package/dist/chunk-XYAZJ3WX.cjs +56 -0
  20. package/dist/chunk-XYAZJ3WX.cjs.map +1 -0
  21. package/dist/cli.js +1 -1
  22. package/dist/head.cjs +10 -2
  23. package/dist/head.cjs.map +1 -1
  24. package/dist/head.d.cts +61 -1
  25. package/dist/head.d.ts +61 -1
  26. package/dist/head.js +9 -1
  27. package/dist/hreflang-_VbSuWYD.d.cts +29 -0
  28. package/dist/hreflang-_VbSuWYD.d.ts +29 -0
  29. package/dist/index.cjs +173 -38
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +3 -2
  32. package/dist/index.d.ts +3 -2
  33. package/dist/index.js +336 -201
  34. package/dist/index.js.map +1 -1
  35. package/dist/next.cjs +11 -3
  36. package/dist/next.cjs.map +1 -1
  37. package/dist/next.d.cts +2 -1
  38. package/dist/next.d.ts +2 -1
  39. package/dist/next.js +9 -1
  40. package/dist/next.js.map +1 -1
  41. package/dist/{plugin-DoGeZP79.d.cts → plugin-HFuWZsJu.d.cts} +68 -1
  42. package/dist/{plugin-DQdThyxG.d.ts → plugin-oQUCim56.d.ts} +68 -1
  43. package/dist/server.cjs +2 -2
  44. package/dist/server.cjs.map +1 -1
  45. package/dist/server.d.cts +6 -8
  46. package/dist/server.d.ts +6 -8
  47. package/dist/server.js +1 -1
  48. package/dist/server.js.map +1 -1
  49. package/package.json +2 -2
  50. package/dist/chunk-3OK3S2F7.cjs.map +0 -1
  51. package/dist/chunk-FUUWBQE2.cjs.map +0 -1
  52. package/dist/chunk-HHO2AKAP.js.map +0 -1
  53. package/dist/chunk-KIEO6QG3.js.map +0 -1
  54. package/dist/chunk-Y46ACXM4.cjs.map +0 -1
  55. package/dist/chunk-Z5AOUU4H.js.map +0 -1
  56. /package/dist/{SeoPreview-UNQBKTQO.js.map → SeoPreview-TATJQFMP.js.map} +0 -0
package/dist/next.cjs CHANGED
@@ -3,7 +3,12 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkFUUWBQE2cjs = require('./chunk-FUUWBQE2.cjs');
6
+
7
+
8
+ var _chunkOULUDJPIcjs = require('./chunk-OULUDJPI.cjs');
9
+
10
+
11
+ var _chunkXYAZJ3WXcjs = require('./chunk-XYAZJ3WX.cjs');
7
12
 
8
13
 
9
14
 
@@ -100,7 +105,7 @@ function SeoMetaTags({
100
105
  imageUrlResolver
101
106
  }) {
102
107
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t;
103
- const meta = _chunkFUUWBQE2cjs.buildSeoMeta.call(void 0, { seo: data, baseUrl, path, defaults, imageUrlResolver });
108
+ const meta = _chunkOULUDJPIcjs.buildSeoMeta.call(void 0, { seo: data, baseUrl, path, defaults, imageUrlResolver });
104
109
  const robotsContent = [
105
110
  ((_a = meta.robots) == null ? void 0 : _a.index) === false ? "noindex" : "index",
106
111
  ((_b = meta.robots) == null ? void 0 : _b.follow) === false ? "nofollow" : "follow",
@@ -222,5 +227,8 @@ function SeoMetaTags({
222
227
 
223
228
 
224
229
 
225
- exports.AggregateRatingSchema = _chunkR2U7JF7Ucjs.AggregateRatingSchema; exports.ArticleSchema = _chunkR2U7JF7Ucjs.ArticleSchema; exports.BlogPostingSchema = _chunkR2U7JF7Ucjs.BlogPostingSchema; exports.BookSchema = _chunkR2U7JF7Ucjs.BookSchema; exports.BrandSchema = _chunkR2U7JF7Ucjs.BrandSchema; exports.BreadcrumbListSchema = _chunkR2U7JF7Ucjs.BreadcrumbListSchema; exports.ContactPointSchema = _chunkR2U7JF7Ucjs.ContactPointSchema; exports.CountrySchema = _chunkR2U7JF7Ucjs.CountrySchema; exports.CourseSchema = _chunkR2U7JF7Ucjs.CourseSchema; exports.EventSchema = _chunkR2U7JF7Ucjs.EventSchema; exports.FAQPageSchema = _chunkR2U7JF7Ucjs.FAQPageSchema; exports.HowToSchema = _chunkR2U7JF7Ucjs.HowToSchema; exports.ImageObjectSchema = _chunkR2U7JF7Ucjs.ImageObjectSchema; exports.ItemListSchema = _chunkR2U7JF7Ucjs.ItemListSchema; exports.JobPostingSchema = _chunkR2U7JF7Ucjs.JobPostingSchema; exports.LegalServiceSchema = _chunkR2U7JF7Ucjs.LegalServiceSchema; exports.LocalBusinessSchema = _chunkR2U7JF7Ucjs.LocalBusinessSchema; exports.MovieSchema = _chunkR2U7JF7Ucjs.MovieSchema; exports.MusicAlbumSchema = _chunkR2U7JF7Ucjs.MusicAlbumSchema; exports.MusicRecordingSchema = _chunkR2U7JF7Ucjs.MusicRecordingSchema; exports.NewsArticleSchema = _chunkR2U7JF7Ucjs.NewsArticleSchema; exports.OfferSchema = _chunkR2U7JF7Ucjs.OfferSchema; exports.OpinionNewsArticleSchema = _chunkR2U7JF7Ucjs.OpinionNewsArticleSchema; exports.OrganizationSchema = _chunk5XTQRILLcjs.OrganizationSchema; exports.PersonSchema = _chunkR2U7JF7Ucjs.PersonSchema; exports.PlaceSchema = _chunkR2U7JF7Ucjs.PlaceSchema; exports.PostalAddressSchema = _chunkR2U7JF7Ucjs.PostalAddressSchema; exports.ProductSchema = _chunkR2U7JF7Ucjs.ProductSchema; exports.ProfilePageSchema = _chunkR2U7JF7Ucjs.ProfilePageSchema; exports.RecipeSchema = _chunkR2U7JF7Ucjs.RecipeSchema; exports.RestaurantSchema = _chunkR2U7JF7Ucjs.RestaurantSchema; exports.ReviewSchema = _chunkR2U7JF7Ucjs.ReviewSchema; exports.SchemaOrgScripts = _chunk5XTQRILLcjs.SchemaOrgScripts; exports.SeoMetaTags = SeoMetaTags; exports.ServiceSchema = _chunkR2U7JF7Ucjs.ServiceSchema; exports.SoftwareApplicationSchema = _chunkR2U7JF7Ucjs.SoftwareApplicationSchema; exports.VideoObjectSchema = _chunkR2U7JF7Ucjs.VideoObjectSchema; exports.WebApplicationSchema = _chunkR2U7JF7Ucjs.WebApplicationSchema; exports.WebPageSchema = _chunkR2U7JF7Ucjs.WebPageSchema; exports.WebsiteSchema = _chunk5XTQRILLcjs.WebsiteSchema; exports.buildAggregateRatingJsonLd = _chunkR2U7JF7Ucjs.buildAggregateRatingJsonLd; exports.buildArticleJsonLd = _chunkR2U7JF7Ucjs.buildArticleJsonLd; exports.buildBlogPostingJsonLd = _chunkR2U7JF7Ucjs.buildBlogPostingJsonLd; exports.buildBookJsonLd = _chunkR2U7JF7Ucjs.buildBookJsonLd; exports.buildBrandJsonLd = _chunkR2U7JF7Ucjs.buildBrandJsonLd; exports.buildBreadcrumbListJsonLd = _chunkR2U7JF7Ucjs.buildBreadcrumbListJsonLd; exports.buildContactPointJsonLd = _chunkR2U7JF7Ucjs.buildContactPointJsonLd; exports.buildCountryJsonLd = _chunkR2U7JF7Ucjs.buildCountryJsonLd; exports.buildCourseJsonLd = _chunkR2U7JF7Ucjs.buildCourseJsonLd; exports.buildEventJsonLd = _chunkR2U7JF7Ucjs.buildEventJsonLd; exports.buildFAQPageJsonLd = _chunkR2U7JF7Ucjs.buildFAQPageJsonLd; exports.buildHowToJsonLd = _chunkR2U7JF7Ucjs.buildHowToJsonLd; exports.buildImageObjectJsonLd = _chunkR2U7JF7Ucjs.buildImageObjectJsonLd; exports.buildItemListJsonLd = _chunkR2U7JF7Ucjs.buildItemListJsonLd; exports.buildJobPostingJsonLd = _chunkR2U7JF7Ucjs.buildJobPostingJsonLd; exports.buildLegalServiceJsonLd = _chunkR2U7JF7Ucjs.buildLegalServiceJsonLd; exports.buildLocalBusinessJsonLd = _chunkR2U7JF7Ucjs.buildLocalBusinessJsonLd; exports.buildMovieJsonLd = _chunkR2U7JF7Ucjs.buildMovieJsonLd; exports.buildMusicAlbumJsonLd = _chunkR2U7JF7Ucjs.buildMusicAlbumJsonLd; exports.buildMusicRecordingJsonLd = _chunkR2U7JF7Ucjs.buildMusicRecordingJsonLd; exports.buildNewsArticleJsonLd = _chunkR2U7JF7Ucjs.buildNewsArticleJsonLd; exports.buildOfferJsonLd = _chunkR2U7JF7Ucjs.buildOfferJsonLd; exports.buildOpinionNewsArticleJsonLd = _chunkR2U7JF7Ucjs.buildOpinionNewsArticleJsonLd; exports.buildOrganizationJsonLd = _chunk5XTQRILLcjs.buildOrganizationJsonLd; exports.buildPersonJsonLd = _chunkR2U7JF7Ucjs.buildPersonJsonLd; exports.buildPlaceJsonLd = _chunkR2U7JF7Ucjs.buildPlaceJsonLd; exports.buildPostalAddressJsonLd = _chunkR2U7JF7Ucjs.buildPostalAddressJsonLd; exports.buildProductJsonLd = _chunkR2U7JF7Ucjs.buildProductJsonLd; exports.buildProfilePageJsonLd = _chunkR2U7JF7Ucjs.buildProfilePageJsonLd; exports.buildRecipeJsonLd = _chunkR2U7JF7Ucjs.buildRecipeJsonLd; exports.buildRestaurantJsonLd = _chunkR2U7JF7Ucjs.buildRestaurantJsonLd; exports.buildReviewJsonLd = _chunkR2U7JF7Ucjs.buildReviewJsonLd; exports.buildSchemaOrgJsonLd = _chunk5XTQRILLcjs.buildSchemaOrgJsonLd; exports.buildSchemaOrgJsonLds = _chunk5XTQRILLcjs.buildSchemaOrgJsonLds; exports.buildSeoHead = _chunkFUUWBQE2cjs.buildSeoHead; exports.buildSeoMeta = _chunkFUUWBQE2cjs.buildSeoMeta; exports.buildServiceJsonLd = _chunkR2U7JF7Ucjs.buildServiceJsonLd; exports.buildSoftwareApplicationJsonLd = _chunkR2U7JF7Ucjs.buildSoftwareApplicationJsonLd; exports.buildVideoObjectJsonLd = _chunkR2U7JF7Ucjs.buildVideoObjectJsonLd; exports.buildWebApplicationJsonLd = _chunkR2U7JF7Ucjs.buildWebApplicationJsonLd; exports.buildWebPageJsonLd = _chunkR2U7JF7Ucjs.buildWebPageJsonLd; exports.buildWebsiteJsonLd = _chunk5XTQRILLcjs.buildWebsiteJsonLd; exports.sanitizeOGType = _chunkFUUWBQE2cjs.sanitizeOGType; exports.sanitizeTwitterCard = _chunkFUUWBQE2cjs.sanitizeTwitterCard;
230
+
231
+
232
+
233
+ exports.AggregateRatingSchema = _chunkR2U7JF7Ucjs.AggregateRatingSchema; exports.ArticleSchema = _chunkR2U7JF7Ucjs.ArticleSchema; exports.BlogPostingSchema = _chunkR2U7JF7Ucjs.BlogPostingSchema; exports.BookSchema = _chunkR2U7JF7Ucjs.BookSchema; exports.BrandSchema = _chunkR2U7JF7Ucjs.BrandSchema; exports.BreadcrumbListSchema = _chunkR2U7JF7Ucjs.BreadcrumbListSchema; exports.ContactPointSchema = _chunkR2U7JF7Ucjs.ContactPointSchema; exports.CountrySchema = _chunkR2U7JF7Ucjs.CountrySchema; exports.CourseSchema = _chunkR2U7JF7Ucjs.CourseSchema; exports.EventSchema = _chunkR2U7JF7Ucjs.EventSchema; exports.FAQPageSchema = _chunkR2U7JF7Ucjs.FAQPageSchema; exports.HowToSchema = _chunkR2U7JF7Ucjs.HowToSchema; exports.ImageObjectSchema = _chunkR2U7JF7Ucjs.ImageObjectSchema; exports.ItemListSchema = _chunkR2U7JF7Ucjs.ItemListSchema; exports.JobPostingSchema = _chunkR2U7JF7Ucjs.JobPostingSchema; exports.LegalServiceSchema = _chunkR2U7JF7Ucjs.LegalServiceSchema; exports.LocalBusinessSchema = _chunkR2U7JF7Ucjs.LocalBusinessSchema; exports.MovieSchema = _chunkR2U7JF7Ucjs.MovieSchema; exports.MusicAlbumSchema = _chunkR2U7JF7Ucjs.MusicAlbumSchema; exports.MusicRecordingSchema = _chunkR2U7JF7Ucjs.MusicRecordingSchema; exports.NewsArticleSchema = _chunkR2U7JF7Ucjs.NewsArticleSchema; exports.OfferSchema = _chunkR2U7JF7Ucjs.OfferSchema; exports.OpinionNewsArticleSchema = _chunkR2U7JF7Ucjs.OpinionNewsArticleSchema; exports.OrganizationSchema = _chunk5XTQRILLcjs.OrganizationSchema; exports.PersonSchema = _chunkR2U7JF7Ucjs.PersonSchema; exports.PlaceSchema = _chunkR2U7JF7Ucjs.PlaceSchema; exports.PostalAddressSchema = _chunkR2U7JF7Ucjs.PostalAddressSchema; exports.ProductSchema = _chunkR2U7JF7Ucjs.ProductSchema; exports.ProfilePageSchema = _chunkR2U7JF7Ucjs.ProfilePageSchema; exports.RecipeSchema = _chunkR2U7JF7Ucjs.RecipeSchema; exports.RestaurantSchema = _chunkR2U7JF7Ucjs.RestaurantSchema; exports.ReviewSchema = _chunkR2U7JF7Ucjs.ReviewSchema; exports.SchemaOrgScripts = _chunk5XTQRILLcjs.SchemaOrgScripts; exports.SeoMetaTags = SeoMetaTags; exports.ServiceSchema = _chunkR2U7JF7Ucjs.ServiceSchema; exports.SoftwareApplicationSchema = _chunkR2U7JF7Ucjs.SoftwareApplicationSchema; exports.VideoObjectSchema = _chunkR2U7JF7Ucjs.VideoObjectSchema; exports.WebApplicationSchema = _chunkR2U7JF7Ucjs.WebApplicationSchema; exports.WebPageSchema = _chunkR2U7JF7Ucjs.WebPageSchema; exports.WebsiteSchema = _chunk5XTQRILLcjs.WebsiteSchema; exports.buildAggregateRatingJsonLd = _chunkR2U7JF7Ucjs.buildAggregateRatingJsonLd; exports.buildArticleJsonLd = _chunkR2U7JF7Ucjs.buildArticleJsonLd; exports.buildBlogPostingJsonLd = _chunkR2U7JF7Ucjs.buildBlogPostingJsonLd; exports.buildBookJsonLd = _chunkR2U7JF7Ucjs.buildBookJsonLd; exports.buildBrandJsonLd = _chunkR2U7JF7Ucjs.buildBrandJsonLd; exports.buildBreadcrumbListJsonLd = _chunkR2U7JF7Ucjs.buildBreadcrumbListJsonLd; exports.buildContactPointJsonLd = _chunkR2U7JF7Ucjs.buildContactPointJsonLd; exports.buildCountryJsonLd = _chunkR2U7JF7Ucjs.buildCountryJsonLd; exports.buildCourseJsonLd = _chunkR2U7JF7Ucjs.buildCourseJsonLd; exports.buildEventJsonLd = _chunkR2U7JF7Ucjs.buildEventJsonLd; exports.buildFAQPageJsonLd = _chunkR2U7JF7Ucjs.buildFAQPageJsonLd; exports.buildHowToJsonLd = _chunkR2U7JF7Ucjs.buildHowToJsonLd; exports.buildHreflangs = _chunkXYAZJ3WXcjs.buildHreflangs; exports.buildImageObjectJsonLd = _chunkR2U7JF7Ucjs.buildImageObjectJsonLd; exports.buildItemListJsonLd = _chunkR2U7JF7Ucjs.buildItemListJsonLd; exports.buildJobPostingJsonLd = _chunkR2U7JF7Ucjs.buildJobPostingJsonLd; exports.buildLegalServiceJsonLd = _chunkR2U7JF7Ucjs.buildLegalServiceJsonLd; exports.buildLlmsTxt = _chunkOULUDJPIcjs.buildLlmsTxt; exports.buildLocalBusinessJsonLd = _chunkR2U7JF7Ucjs.buildLocalBusinessJsonLd; exports.buildMovieJsonLd = _chunkR2U7JF7Ucjs.buildMovieJsonLd; exports.buildMusicAlbumJsonLd = _chunkR2U7JF7Ucjs.buildMusicAlbumJsonLd; exports.buildMusicRecordingJsonLd = _chunkR2U7JF7Ucjs.buildMusicRecordingJsonLd; exports.buildNewsArticleJsonLd = _chunkR2U7JF7Ucjs.buildNewsArticleJsonLd; exports.buildOfferJsonLd = _chunkR2U7JF7Ucjs.buildOfferJsonLd; exports.buildOpinionNewsArticleJsonLd = _chunkR2U7JF7Ucjs.buildOpinionNewsArticleJsonLd; exports.buildOrganizationJsonLd = _chunk5XTQRILLcjs.buildOrganizationJsonLd; exports.buildPersonJsonLd = _chunkR2U7JF7Ucjs.buildPersonJsonLd; exports.buildPlaceJsonLd = _chunkR2U7JF7Ucjs.buildPlaceJsonLd; exports.buildPostalAddressJsonLd = _chunkR2U7JF7Ucjs.buildPostalAddressJsonLd; exports.buildProductJsonLd = _chunkR2U7JF7Ucjs.buildProductJsonLd; exports.buildProfilePageJsonLd = _chunkR2U7JF7Ucjs.buildProfilePageJsonLd; exports.buildRecipeJsonLd = _chunkR2U7JF7Ucjs.buildRecipeJsonLd; exports.buildRestaurantJsonLd = _chunkR2U7JF7Ucjs.buildRestaurantJsonLd; exports.buildReviewJsonLd = _chunkR2U7JF7Ucjs.buildReviewJsonLd; exports.buildSchemaOrgJsonLd = _chunk5XTQRILLcjs.buildSchemaOrgJsonLd; exports.buildSchemaOrgJsonLds = _chunk5XTQRILLcjs.buildSchemaOrgJsonLds; exports.buildSeoHead = _chunkOULUDJPIcjs.buildSeoHead; exports.buildSeoMeta = _chunkOULUDJPIcjs.buildSeoMeta; exports.buildServiceJsonLd = _chunkR2U7JF7Ucjs.buildServiceJsonLd; exports.buildSoftwareApplicationJsonLd = _chunkR2U7JF7Ucjs.buildSoftwareApplicationJsonLd; exports.buildVideoObjectJsonLd = _chunkR2U7JF7Ucjs.buildVideoObjectJsonLd; exports.buildWebApplicationJsonLd = _chunkR2U7JF7Ucjs.buildWebApplicationJsonLd; exports.buildWebPageJsonLd = _chunkR2U7JF7Ucjs.buildWebPageJsonLd; exports.buildWebsiteJsonLd = _chunk5XTQRILLcjs.buildWebsiteJsonLd; exports.docsToLlmsSection = _chunkOULUDJPIcjs.docsToLlmsSection; exports.sanitizeOGType = _chunkOULUDJPIcjs.sanitizeOGType; exports.sanitizeTwitterCard = _chunkOULUDJPIcjs.sanitizeTwitterCard;
226
234
  //# sourceMappingURL=next.cjs.map
package/dist/next.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/hardik/GITHUB/sanity-plugin-seofields/npm/dist/next.cjs","../src/helpers/SeoMetaTags.tsx"],"names":["Fragment"],"mappings":"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,OAAA,mBAAU,6BAAA,MAAC,EAAA,EAAK,QAAA,EAAS,iBAAA,EAAkB,OAAA,EAAS,MAAA,CAAO,GAAA,CAAI,MAAM,EAAA,CAAG,CAAA;AAAA,QAC5E,GAAA,CAAI,IAAA,mBAAO,6BAAA,MAAC,EAAA,EAAK,QAAA,EAAS,cAAA,EAAe,OAAA,EAAS,GAAA,CAAI,IAAA,CAAK;AAAA,MAAA,EAAA,CAAA,EAJ/C,CAAA,OAAA,EAAU,CAAC,CAAA,CAAA;AAK1B,IAAA;AAII,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AAGA,IAAA;AAMJ,IAAA;AAKI,IAAA;AACR,EAAA;AAEJ;ADvBuB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/Users/hardik/GITHUB/sanity-plugin-seofields/npm/dist/next.cjs","sourcesContent":[null,"/**\n * <SeoMetaTags> — Framework-agnostic React SEO meta tag renderer.\n *\n * Renders all SEO meta tags as plain React elements.\n * Place it inside your framework's <Head> component:\n *\n * @example Next.js Pages Router\n * ```tsx\n * import Head from 'next/head'\n * import { SeoMetaTags } from 'sanity-plugin-seofields/next'\n *\n * export default function Page({ seo }) {\n * return (\n * <>\n * <Head>\n * <SeoMetaTags\n * data={seo}\n * baseUrl=\"https://example.com\"\n * path=\"/about\"\n * defaults={{ title: 'My Site', siteName: 'My Site' }}\n * imageUrlResolver={(img) => urlFor(img).width(1200).url()}\n * />\n * </Head>\n * <main>...</main>\n * </>\n * )\n * }\n * ```\n *\n * @example React SSR (inside a framework <Head> slot)\n * ```tsx\n * <Head>\n * <SeoMetaTags data={seo} baseUrl=\"https://example.com\" path=\"/\" />\n * </Head>\n * ```\n */\nimport {Fragment, type JSX} from 'react'\n\nimport type {SanityImage, SanityImageWithAlt, SeoFields} from '../types'\nimport {buildSeoMeta, type BuildSeoMetaOptions} from './seoMeta'\n\n// ─── Props ────────────────────────────────────────────────────────────────────\n\nexport interface SeoMetaTagsProps {\n /**\n * The raw SEO object from Sanity.\n * Pass `null` / `undefined` to render only the defaults.\n */\n data?: Partial<SeoFields> | null\n\n /**\n * Base URL of your site, e.g. \"https://example.com\".\n * Used for canonical link, og:url fallback.\n */\n baseUrl?: string\n\n /**\n * Current page path, e.g. \"/about\".\n * Defaults to \"\".\n */\n path?: string\n\n /**\n * Default values used when SEO fields are missing.\n */\n defaults?: BuildSeoMetaOptions['defaults']\n\n /**\n * Resolve a Sanity image asset reference to a full URL string.\n *\n * @example\n * imageUrlResolver={(img) => urlFor(img).width(1200).url()}\n */\n imageUrlResolver?: (image: SanityImage | SanityImageWithAlt) => string | null | undefined\n}\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\n/**\n * Renders all SEO meta tags for a page as plain React elements.\n * Intended to be placed inside your framework's <Head> / <head> component.\n *\n * Renders:\n * - `<title>`\n * - `<meta name=\"description\">`\n * - `<meta name=\"keywords\">`\n * - `<meta name=\"robots\">`\n * - OpenGraph meta tags (`og:*`)\n * - Twitter Card meta tags (`twitter:*`)\n * - Any custom `seo.metaAttributes` as `<meta name=\"...\" content=\"...\">`\n */\nexport function SeoMetaTags({\n data,\n baseUrl,\n path,\n defaults,\n imageUrlResolver,\n}: SeoMetaTagsProps): JSX.Element {\n const meta = buildSeoMeta({seo: data, baseUrl, path, defaults, imageUrlResolver})\n\n const robotsContent = [\n meta.robots?.index === false ? 'noindex' : 'index',\n meta.robots?.follow === false ? 'nofollow' : 'follow',\n meta.robots?.notranslate ? 'notranslate' : null,\n meta.robots?.noimageindex ? 'noimageindex' : null,\n ]\n .filter(Boolean)\n .join(', ')\n\n return (\n <>\n {/* ── Title ── */}\n {meta.title && <title>{meta.title}</title>}\n\n {/* ── Basic meta ── */}\n {meta.description && <meta name=\"description\" content={meta.description} />}\n {meta.keywords?.length ? <meta name=\"keywords\" content={meta.keywords.join(', ')} /> : null}\n <meta name=\"robots\" content={robotsContent} />\n <meta name=\"googlebot\" content={robotsContent} />\n\n {/* ── Open Graph ── */}\n {meta.openGraph?.type && <meta property=\"og:type\" content={meta.openGraph.type} />}\n {meta.openGraph?.url && <meta property=\"og:url\" content={meta.openGraph.url} />}\n {meta.openGraph?.title && <meta property=\"og:title\" content={meta.openGraph.title} />}\n {meta.openGraph?.description && (\n <meta property=\"og:description\" content={meta.openGraph.description} />\n )}\n {meta.openGraph?.siteName && (\n <meta property=\"og:site_name\" content={meta.openGraph.siteName} />\n )}\n {meta.openGraph?.images?.map((img, i) => (\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={`og-img-${i}`}>\n <meta property=\"og:image\" content={img.url} />\n {img.width && <meta property=\"og:image:width\" content={String(img.width)} />}\n {img.height && <meta property=\"og:image:height\" content={String(img.height)} />}\n {img.alt && <meta property=\"og:image:alt\" content={img.alt} />}\n </Fragment>\n ))}\n\n {/* ── Twitter Card ── */}\n {meta.twitter?.card && <meta name=\"twitter:card\" content={meta.twitter.card} />}\n {meta.twitter?.site && <meta name=\"twitter:site\" content={meta.twitter.site} />}\n {meta.twitter?.creator && <meta name=\"twitter:creator\" content={meta.twitter.creator} />}\n {meta.twitter?.title && <meta name=\"twitter:title\" content={meta.twitter.title} />}\n {meta.twitter?.description && (\n <meta name=\"twitter:description\" content={meta.twitter.description} />\n )}\n {meta.twitter?.images?.map((url, i) => (\n <meta key={`tw-img-${i}`} name=\"twitter:image\" content={url} />\n ))}\n\n {/* ── Custom meta attributes ── */}\n {meta.other &&\n Object.entries(meta.other).map(([name, content]) => (\n <meta key={`custom-${name}`} name={name} content={content} />\n ))}\n\n {/* ── Canonical URL ── */}\n {meta.alternates?.canonical && <link rel=\"canonical\" href={meta.alternates.canonical} />}\n </>\n )\n}\n\nexport default SeoMetaTags\n"]}
1
+ {"version":3,"sources":["/Users/hardik/GITHUB/sanity-plugin-seofields/npm/dist/next.cjs","../src/helpers/SeoMetaTags.tsx"],"names":["Fragment"],"mappings":"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AA,CAAG,CAAA;AAAA,QACzE,GAAA,CAAI,OAAA,mBAAU,6BAAA,MAAC,EAAA,EAAK,QAAA,EAAS,iBAAA,EAAkB,OAAA,EAAS,MAAA,CAAO,GAAA,CAAI,MAAM,EAAA,CAAG,CAAA;AAAA,QAC5E,GAAA,CAAI,IAAA,mBAAO,6BAAA,MAAC,EAAA,EAAK,QAAA,EAAS,cAAA,EAAe,OAAA,EAAS,GAAA,CAAI,IAAA,CAAK;AAAA,MAAA,EAAA,CAAA,EAJ/C,CAAA,OAAA,EAAU,CAAC,CAAA,CAAA;AAK1B,IAAA;AAII,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AAGA,IAAA;AAMJ,IAAA;AAKI,IAAA;AACR,EAAA;AAEJ;ADlBuB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/Users/hardik/GITHUB/sanity-plugin-seofields/npm/dist/next.cjs","sourcesContent":[null,"/**\n * <SeoMetaTags> — Framework-agnostic React SEO meta tag renderer.\n *\n * Renders all SEO meta tags as plain React elements.\n * Place it inside your framework's <Head> component:\n *\n * @example Next.js Pages Router\n * ```tsx\n * import Head from 'next/head'\n * import { SeoMetaTags } from 'sanity-plugin-seofields/next'\n *\n * export default function Page({ seo }) {\n * return (\n * <>\n * <Head>\n * <SeoMetaTags\n * data={seo}\n * baseUrl=\"https://example.com\"\n * path=\"/about\"\n * defaults={{ title: 'My Site', siteName: 'My Site' }}\n * imageUrlResolver={(img) => urlFor(img).width(1200).url()}\n * />\n * </Head>\n * <main>...</main>\n * </>\n * )\n * }\n * ```\n *\n * @example React SSR (inside a framework <Head> slot)\n * ```tsx\n * <Head>\n * <SeoMetaTags data={seo} baseUrl=\"https://example.com\" path=\"/\" />\n * </Head>\n * ```\n */\nimport {Fragment, type JSX} from 'react'\n\nimport type {SanityImage, SanityImageWithAlt, SeoFields} from '../types'\nimport {buildSeoMeta, type BuildSeoMetaOptions} from './seoMeta'\n\n// ─── Props ────────────────────────────────────────────────────────────────────\n\nexport interface SeoMetaTagsProps {\n /**\n * The raw SEO object from Sanity.\n * Pass `null` / `undefined` to render only the defaults.\n */\n data?: Partial<SeoFields> | null\n\n /**\n * Base URL of your site, e.g. \"https://example.com\".\n * Used for canonical link, og:url fallback.\n */\n baseUrl?: string\n\n /**\n * Current page path, e.g. \"/about\".\n * Defaults to \"\".\n */\n path?: string\n\n /**\n * Default values used when SEO fields are missing.\n */\n defaults?: BuildSeoMetaOptions['defaults']\n\n /**\n * Resolve a Sanity image asset reference to a full URL string.\n *\n * @example\n * imageUrlResolver={(img) => urlFor(img).width(1200).url()}\n */\n imageUrlResolver?: (image: SanityImage | SanityImageWithAlt) => string | null | undefined\n}\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\n/**\n * Renders all SEO meta tags for a page as plain React elements.\n * Intended to be placed inside your framework's <Head> / <head> component.\n *\n * Renders:\n * - `<title>`\n * - `<meta name=\"description\">`\n * - `<meta name=\"keywords\">`\n * - `<meta name=\"robots\">`\n * - OpenGraph meta tags (`og:*`)\n * - Twitter Card meta tags (`twitter:*`)\n * - Any custom `seo.metaAttributes` as `<meta name=\"...\" content=\"...\">`\n */\nexport function SeoMetaTags({\n data,\n baseUrl,\n path,\n defaults,\n imageUrlResolver,\n}: SeoMetaTagsProps): JSX.Element {\n const meta = buildSeoMeta({seo: data, baseUrl, path, defaults, imageUrlResolver})\n\n const robotsContent = [\n meta.robots?.index === false ? 'noindex' : 'index',\n meta.robots?.follow === false ? 'nofollow' : 'follow',\n meta.robots?.notranslate ? 'notranslate' : null,\n meta.robots?.noimageindex ? 'noimageindex' : null,\n ]\n .filter(Boolean)\n .join(', ')\n\n return (\n <>\n {/* ── Title ── */}\n {meta.title && <title>{meta.title}</title>}\n\n {/* ── Basic meta ── */}\n {meta.description && <meta name=\"description\" content={meta.description} />}\n {meta.keywords?.length ? <meta name=\"keywords\" content={meta.keywords.join(', ')} /> : null}\n <meta name=\"robots\" content={robotsContent} />\n <meta name=\"googlebot\" content={robotsContent} />\n\n {/* ── Open Graph ── */}\n {meta.openGraph?.type && <meta property=\"og:type\" content={meta.openGraph.type} />}\n {meta.openGraph?.url && <meta property=\"og:url\" content={meta.openGraph.url} />}\n {meta.openGraph?.title && <meta property=\"og:title\" content={meta.openGraph.title} />}\n {meta.openGraph?.description && (\n <meta property=\"og:description\" content={meta.openGraph.description} />\n )}\n {meta.openGraph?.siteName && (\n <meta property=\"og:site_name\" content={meta.openGraph.siteName} />\n )}\n {meta.openGraph?.images?.map((img, i) => (\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={`og-img-${i}`}>\n <meta property=\"og:image\" content={img.url} />\n {img.width && <meta property=\"og:image:width\" content={String(img.width)} />}\n {img.height && <meta property=\"og:image:height\" content={String(img.height)} />}\n {img.alt && <meta property=\"og:image:alt\" content={img.alt} />}\n </Fragment>\n ))}\n\n {/* ── Twitter Card ── */}\n {meta.twitter?.card && <meta name=\"twitter:card\" content={meta.twitter.card} />}\n {meta.twitter?.site && <meta name=\"twitter:site\" content={meta.twitter.site} />}\n {meta.twitter?.creator && <meta name=\"twitter:creator\" content={meta.twitter.creator} />}\n {meta.twitter?.title && <meta name=\"twitter:title\" content={meta.twitter.title} />}\n {meta.twitter?.description && (\n <meta name=\"twitter:description\" content={meta.twitter.description} />\n )}\n {meta.twitter?.images?.map((url, i) => (\n <meta key={`tw-img-${i}`} name=\"twitter:image\" content={url} />\n ))}\n\n {/* ── Custom meta attributes ── */}\n {meta.other &&\n Object.entries(meta.other).map(([name, content]) => (\n <meta key={`custom-${name}`} name={name} content={content} />\n ))}\n\n {/* ── Canonical URL ── */}\n {meta.alternates?.canonical && <link rel=\"canonical\" href={meta.alternates.canonical} />}\n </>\n )\n}\n\nexport default SeoMetaTags\n"]}
package/dist/next.d.cts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { BuildSeoMetaOptions } from './head.cjs';
2
- export { SeoFieldsInput, SeoHead, SeoHeadLinkTag, SeoHeadMetaTag, SeoMetaDefaults, SeoMetadata, buildSeoHead, buildSeoMeta, sanitizeOGType, sanitizeTwitterCard } from './head.cjs';
2
+ export { BuildLlmsTxtOptions, DocsToLlmsSectionOptions, LlmsDoc, LlmsLink, LlmsSection, SeoFieldsInput, SeoHead, SeoHeadLinkTag, SeoHeadMetaTag, SeoMetaDefaults, SeoMetadata, buildLlmsTxt, buildSeoHead, buildSeoMeta, docsToLlmsSection, sanitizeOGType, sanitizeTwitterCard } from './head.cjs';
3
3
  import { JSX } from 'react';
4
4
  import { S as SeoFields, a as SanityImage, b as SanityImageWithAlt } from './types-DxlPXihz.cjs';
5
+ export { B as BuildHreflangsOptions, H as HreflangLinkEntry, a as HreflangTranslation, b as buildHreflangs } from './hreflang-_VbSuWYD.cjs';
5
6
  export { S as SchemaOrgScripts, a as SchemaOrgScriptsProps, b as buildSchemaOrgJsonLd, c as buildSchemaOrgJsonLds } from './types-DP-DiW6f.cjs';
6
7
  export { A as AggregateRatingSchema, a as AggregateRatingSchemaProps, b as ArticleSchema, c as ArticleSchemaProps, B as BlogPostingSchema, d as BlogPostingSchemaProps, e as BookSchema, f as BookSchemaProps, g as BrandSchema, h as BrandSchemaProps, i as BreadcrumbListSchema, j as BreadcrumbListSchemaProps, C as ContactPointSchema, k as ContactPointSchemaProps, l as CountrySchema, m as CountrySchemaProps, n as CourseSchema, o as CourseSchemaProps, E as EventSchema, p as EventSchemaProps, F as FAQPageSchema, q as FAQPageSchemaProps, H as HowToSchema, r as HowToSchemaProps, I as ImageObjectSchema, s as ImageObjectSchemaProps, t as ItemListSchema, u as ItemListSchemaProps, J as JobPostingSchema, v as JobPostingSchemaProps, L as LegalServiceSchema, w as LegalServiceSchemaProps, x as LocalBusinessSchema, y as LocalBusinessSchemaProps, M as MovieSchema, z as MovieSchemaProps, D as MusicAlbumSchema, G as MusicAlbumSchemaProps, K as MusicRecordingSchema, N as MusicRecordingSchemaProps, O as NewsArticleSchema, P as NewsArticleSchemaProps, Q as OfferSchema, R as OfferSchemaProps, S as OpinionNewsArticleSchema, T as OpinionNewsArticleSchemaProps, U as OrganizationSchema, V as OrganizationSchemaProps, W as PersonSchema, X as PersonSchemaProps, Y as PlaceSchema, Z as PlaceSchemaProps, _ as PostalAddressSchema, $ as PostalAddressSchemaProps, a0 as ProductSchema, a1 as ProductSchemaProps, a2 as ProfilePageSchema, a3 as ProfilePageSchemaProps, a4 as RecipeSchema, a5 as RecipeSchemaProps, a6 as RestaurantSchema, a7 as RestaurantSchemaProps, a8 as ReviewSchema, a9 as ReviewSchemaProps, aa as ServiceSchema, ab as ServiceSchemaProps, ac as SoftwareApplicationSchema, ad as SoftwareApplicationSchemaProps, ae as VideoObjectSchema, af as VideoObjectSchemaProps, ag as WebApplicationSchema, ah as WebApplicationSchemaProps, ai as WebPageSchema, aj as WebPageSchemaProps, ak as WebsiteSchema, al as WebsiteSchemaProps, am as buildAggregateRatingJsonLd, an as buildArticleJsonLd, ao as buildBlogPostingJsonLd, ap as buildBookJsonLd, aq as buildBrandJsonLd, ar as buildBreadcrumbListJsonLd, as as buildContactPointJsonLd, at as buildCountryJsonLd, au as buildCourseJsonLd, av as buildEventJsonLd, aw as buildFAQPageJsonLd, ax as buildHowToJsonLd, ay as buildImageObjectJsonLd, az as buildItemListJsonLd, aA as buildJobPostingJsonLd, aB as buildLegalServiceJsonLd, aC as buildLocalBusinessJsonLd, aD as buildMovieJsonLd, aE as buildMusicAlbumJsonLd, aF as buildMusicRecordingJsonLd, aG as buildNewsArticleJsonLd, aH as buildOfferJsonLd, aI as buildOpinionNewsArticleJsonLd, aJ as buildOrganizationJsonLd, aK as buildPersonJsonLd, aL as buildPlaceJsonLd, aM as buildPostalAddressJsonLd, aN as buildProductJsonLd, aO as buildProfilePageJsonLd, aP as buildRecipeJsonLd, aQ as buildRestaurantJsonLd, aR as buildReviewJsonLd, aS as buildServiceJsonLd, aT as buildSoftwareApplicationJsonLd, aU as buildVideoObjectJsonLd, aV as buildWebApplicationJsonLd, aW as buildWebPageJsonLd, aX as buildWebsiteJsonLd } from './component-WYh0z8as.cjs';
7
8
 
package/dist/next.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { BuildSeoMetaOptions } from './head.js';
2
- export { SeoFieldsInput, SeoHead, SeoHeadLinkTag, SeoHeadMetaTag, SeoMetaDefaults, SeoMetadata, buildSeoHead, buildSeoMeta, sanitizeOGType, sanitizeTwitterCard } from './head.js';
2
+ export { BuildLlmsTxtOptions, DocsToLlmsSectionOptions, LlmsDoc, LlmsLink, LlmsSection, SeoFieldsInput, SeoHead, SeoHeadLinkTag, SeoHeadMetaTag, SeoMetaDefaults, SeoMetadata, buildLlmsTxt, buildSeoHead, buildSeoMeta, docsToLlmsSection, sanitizeOGType, sanitizeTwitterCard } from './head.js';
3
3
  import { JSX } from 'react';
4
4
  import { S as SeoFields, a as SanityImage, b as SanityImageWithAlt } from './types-DxlPXihz.js';
5
+ export { B as BuildHreflangsOptions, H as HreflangLinkEntry, a as HreflangTranslation, b as buildHreflangs } from './hreflang-_VbSuWYD.js';
5
6
  export { S as SchemaOrgScripts, a as SchemaOrgScriptsProps, b as buildSchemaOrgJsonLd, c as buildSchemaOrgJsonLds } from './types-DRLUGLtX.js';
6
7
  export { A as AggregateRatingSchema, a as AggregateRatingSchemaProps, b as ArticleSchema, c as ArticleSchemaProps, B as BlogPostingSchema, d as BlogPostingSchemaProps, e as BookSchema, f as BookSchemaProps, g as BrandSchema, h as BrandSchemaProps, i as BreadcrumbListSchema, j as BreadcrumbListSchemaProps, C as ContactPointSchema, k as ContactPointSchemaProps, l as CountrySchema, m as CountrySchemaProps, n as CourseSchema, o as CourseSchemaProps, E as EventSchema, p as EventSchemaProps, F as FAQPageSchema, q as FAQPageSchemaProps, H as HowToSchema, r as HowToSchemaProps, I as ImageObjectSchema, s as ImageObjectSchemaProps, t as ItemListSchema, u as ItemListSchemaProps, J as JobPostingSchema, v as JobPostingSchemaProps, L as LegalServiceSchema, w as LegalServiceSchemaProps, x as LocalBusinessSchema, y as LocalBusinessSchemaProps, M as MovieSchema, z as MovieSchemaProps, D as MusicAlbumSchema, G as MusicAlbumSchemaProps, K as MusicRecordingSchema, N as MusicRecordingSchemaProps, O as NewsArticleSchema, P as NewsArticleSchemaProps, Q as OfferSchema, R as OfferSchemaProps, S as OpinionNewsArticleSchema, T as OpinionNewsArticleSchemaProps, U as OrganizationSchema, V as OrganizationSchemaProps, W as PersonSchema, X as PersonSchemaProps, Y as PlaceSchema, Z as PlaceSchemaProps, _ as PostalAddressSchema, $ as PostalAddressSchemaProps, a0 as ProductSchema, a1 as ProductSchemaProps, a2 as ProfilePageSchema, a3 as ProfilePageSchemaProps, a4 as RecipeSchema, a5 as RecipeSchemaProps, a6 as RestaurantSchema, a7 as RestaurantSchemaProps, a8 as ReviewSchema, a9 as ReviewSchemaProps, aa as ServiceSchema, ab as ServiceSchemaProps, ac as SoftwareApplicationSchema, ad as SoftwareApplicationSchemaProps, ae as VideoObjectSchema, af as VideoObjectSchemaProps, ag as WebApplicationSchema, ah as WebApplicationSchemaProps, ai as WebPageSchema, aj as WebPageSchemaProps, ak as WebsiteSchema, al as WebsiteSchemaProps, am as buildAggregateRatingJsonLd, an as buildArticleJsonLd, ao as buildBlogPostingJsonLd, ap as buildBookJsonLd, aq as buildBrandJsonLd, ar as buildBreadcrumbListJsonLd, as as buildContactPointJsonLd, at as buildCountryJsonLd, au as buildCourseJsonLd, av as buildEventJsonLd, aw as buildFAQPageJsonLd, ax as buildHowToJsonLd, ay as buildImageObjectJsonLd, az as buildItemListJsonLd, aA as buildJobPostingJsonLd, aB as buildLegalServiceJsonLd, aC as buildLocalBusinessJsonLd, aD as buildMovieJsonLd, aE as buildMusicAlbumJsonLd, aF as buildMusicRecordingJsonLd, aG as buildNewsArticleJsonLd, aH as buildOfferJsonLd, aI as buildOpinionNewsArticleJsonLd, aJ as buildOrganizationJsonLd, aK as buildPersonJsonLd, aL as buildPlaceJsonLd, aM as buildPostalAddressJsonLd, aN as buildProductJsonLd, aO as buildProfilePageJsonLd, aP as buildRecipeJsonLd, aQ as buildRestaurantJsonLd, aR as buildReviewJsonLd, aS as buildServiceJsonLd, aT as buildSoftwareApplicationJsonLd, aU as buildVideoObjectJsonLd, aV as buildWebApplicationJsonLd, aW as buildWebPageJsonLd, aX as buildWebsiteJsonLd } from './component-CjT1hvxh.js';
7
8
 
package/dist/next.js CHANGED
@@ -1,9 +1,14 @@
1
1
  import {
2
+ buildLlmsTxt,
2
3
  buildSeoHead,
3
4
  buildSeoMeta,
5
+ docsToLlmsSection,
4
6
  sanitizeOGType,
5
7
  sanitizeTwitterCard
6
- } from "./chunk-KIEO6QG3.js";
8
+ } from "./chunk-XD4HKLEA.js";
9
+ import {
10
+ buildHreflangs
11
+ } from "./chunk-CRCXC45D.js";
7
12
  import {
8
13
  AggregateRatingSchema,
9
14
  ArticleSchema,
@@ -190,10 +195,12 @@ export {
190
195
  buildEventJsonLd,
191
196
  buildFAQPageJsonLd,
192
197
  buildHowToJsonLd,
198
+ buildHreflangs,
193
199
  buildImageObjectJsonLd,
194
200
  buildItemListJsonLd,
195
201
  buildJobPostingJsonLd,
196
202
  buildLegalServiceJsonLd,
203
+ buildLlmsTxt,
197
204
  buildLocalBusinessJsonLd,
198
205
  buildMovieJsonLd,
199
206
  buildMusicAlbumJsonLd,
@@ -220,6 +227,7 @@ export {
220
227
  buildWebApplicationJsonLd,
221
228
  buildWebPageJsonLd,
222
229
  buildWebsiteJsonLd,
230
+ docsToLlmsSection,
223
231
  sanitizeOGType,
224
232
  sanitizeTwitterCard
225
233
  };
package/dist/next.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/helpers/SeoMetaTags.tsx"],"sourcesContent":["/**\n * <SeoMetaTags> — Framework-agnostic React SEO meta tag renderer.\n *\n * Renders all SEO meta tags as plain React elements.\n * Place it inside your framework's <Head> component:\n *\n * @example Next.js Pages Router\n * ```tsx\n * import Head from 'next/head'\n * import { SeoMetaTags } from 'sanity-plugin-seofields/next'\n *\n * export default function Page({ seo }) {\n * return (\n * <>\n * <Head>\n * <SeoMetaTags\n * data={seo}\n * baseUrl=\"https://example.com\"\n * path=\"/about\"\n * defaults={{ title: 'My Site', siteName: 'My Site' }}\n * imageUrlResolver={(img) => urlFor(img).width(1200).url()}\n * />\n * </Head>\n * <main>...</main>\n * </>\n * )\n * }\n * ```\n *\n * @example React SSR (inside a framework <Head> slot)\n * ```tsx\n * <Head>\n * <SeoMetaTags data={seo} baseUrl=\"https://example.com\" path=\"/\" />\n * </Head>\n * ```\n */\nimport {Fragment, type JSX} from 'react'\n\nimport type {SanityImage, SanityImageWithAlt, SeoFields} from '../types'\nimport {buildSeoMeta, type BuildSeoMetaOptions} from './seoMeta'\n\n// ─── Props ────────────────────────────────────────────────────────────────────\n\nexport interface SeoMetaTagsProps {\n /**\n * The raw SEO object from Sanity.\n * Pass `null` / `undefined` to render only the defaults.\n */\n data?: Partial<SeoFields> | null\n\n /**\n * Base URL of your site, e.g. \"https://example.com\".\n * Used for canonical link, og:url fallback.\n */\n baseUrl?: string\n\n /**\n * Current page path, e.g. \"/about\".\n * Defaults to \"\".\n */\n path?: string\n\n /**\n * Default values used when SEO fields are missing.\n */\n defaults?: BuildSeoMetaOptions['defaults']\n\n /**\n * Resolve a Sanity image asset reference to a full URL string.\n *\n * @example\n * imageUrlResolver={(img) => urlFor(img).width(1200).url()}\n */\n imageUrlResolver?: (image: SanityImage | SanityImageWithAlt) => string | null | undefined\n}\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\n/**\n * Renders all SEO meta tags for a page as plain React elements.\n * Intended to be placed inside your framework's <Head> / <head> component.\n *\n * Renders:\n * - `<title>`\n * - `<meta name=\"description\">`\n * - `<meta name=\"keywords\">`\n * - `<meta name=\"robots\">`\n * - OpenGraph meta tags (`og:*`)\n * - Twitter Card meta tags (`twitter:*`)\n * - Any custom `seo.metaAttributes` as `<meta name=\"...\" content=\"...\">`\n */\nexport function SeoMetaTags({\n data,\n baseUrl,\n path,\n defaults,\n imageUrlResolver,\n}: SeoMetaTagsProps): JSX.Element {\n const meta = buildSeoMeta({seo: data, baseUrl, path, defaults, imageUrlResolver})\n\n const robotsContent = [\n meta.robots?.index === false ? 'noindex' : 'index',\n meta.robots?.follow === false ? 'nofollow' : 'follow',\n meta.robots?.notranslate ? 'notranslate' : null,\n meta.robots?.noimageindex ? 'noimageindex' : null,\n ]\n .filter(Boolean)\n .join(', ')\n\n return (\n <>\n {/* ── Title ── */}\n {meta.title && <title>{meta.title}</title>}\n\n {/* ── Basic meta ── */}\n {meta.description && <meta name=\"description\" content={meta.description} />}\n {meta.keywords?.length ? <meta name=\"keywords\" content={meta.keywords.join(', ')} /> : null}\n <meta name=\"robots\" content={robotsContent} />\n <meta name=\"googlebot\" content={robotsContent} />\n\n {/* ── Open Graph ── */}\n {meta.openGraph?.type && <meta property=\"og:type\" content={meta.openGraph.type} />}\n {meta.openGraph?.url && <meta property=\"og:url\" content={meta.openGraph.url} />}\n {meta.openGraph?.title && <meta property=\"og:title\" content={meta.openGraph.title} />}\n {meta.openGraph?.description && (\n <meta property=\"og:description\" content={meta.openGraph.description} />\n )}\n {meta.openGraph?.siteName && (\n <meta property=\"og:site_name\" content={meta.openGraph.siteName} />\n )}\n {meta.openGraph?.images?.map((img, i) => (\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={`og-img-${i}`}>\n <meta property=\"og:image\" content={img.url} />\n {img.width && <meta property=\"og:image:width\" content={String(img.width)} />}\n {img.height && <meta property=\"og:image:height\" content={String(img.height)} />}\n {img.alt && <meta property=\"og:image:alt\" content={img.alt} />}\n </Fragment>\n ))}\n\n {/* ── Twitter Card ── */}\n {meta.twitter?.card && <meta name=\"twitter:card\" content={meta.twitter.card} />}\n {meta.twitter?.site && <meta name=\"twitter:site\" content={meta.twitter.site} />}\n {meta.twitter?.creator && <meta name=\"twitter:creator\" content={meta.twitter.creator} />}\n {meta.twitter?.title && <meta name=\"twitter:title\" content={meta.twitter.title} />}\n {meta.twitter?.description && (\n <meta name=\"twitter:description\" content={meta.twitter.description} />\n )}\n {meta.twitter?.images?.map((url, i) => (\n <meta key={`tw-img-${i}`} name=\"twitter:image\" content={url} />\n ))}\n\n {/* ── Custom meta attributes ── */}\n {meta.other &&\n Object.entries(meta.other).map(([name, content]) => (\n <meta key={`custom-${name}`} name={name} content={content} />\n ))}\n\n {/* ── Canonical URL ── */}\n {meta.alternates?.canonical && <link rel=\"canonical\" href={meta.alternates.canonical} />}\n </>\n )\n}\n\nexport default SeoMetaTags\n"],"mappings":"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","names":["Fragment"]}
1
+ {"version":3,"sources":["../src/helpers/SeoMetaTags.tsx"],"sourcesContent":["/**\n * <SeoMetaTags> — Framework-agnostic React SEO meta tag renderer.\n *\n * Renders all SEO meta tags as plain React elements.\n * Place it inside your framework's <Head> component:\n *\n * @example Next.js Pages Router\n * ```tsx\n * import Head from 'next/head'\n * import { SeoMetaTags } from 'sanity-plugin-seofields/next'\n *\n * export default function Page({ seo }) {\n * return (\n * <>\n * <Head>\n * <SeoMetaTags\n * data={seo}\n * baseUrl=\"https://example.com\"\n * path=\"/about\"\n * defaults={{ title: 'My Site', siteName: 'My Site' }}\n * imageUrlResolver={(img) => urlFor(img).width(1200).url()}\n * />\n * </Head>\n * <main>...</main>\n * </>\n * )\n * }\n * ```\n *\n * @example React SSR (inside a framework <Head> slot)\n * ```tsx\n * <Head>\n * <SeoMetaTags data={seo} baseUrl=\"https://example.com\" path=\"/\" />\n * </Head>\n * ```\n */\nimport {Fragment, type JSX} from 'react'\n\nimport type {SanityImage, SanityImageWithAlt, SeoFields} from '../types'\nimport {buildSeoMeta, type BuildSeoMetaOptions} from './seoMeta'\n\n// ─── Props ────────────────────────────────────────────────────────────────────\n\nexport interface SeoMetaTagsProps {\n /**\n * The raw SEO object from Sanity.\n * Pass `null` / `undefined` to render only the defaults.\n */\n data?: Partial<SeoFields> | null\n\n /**\n * Base URL of your site, e.g. \"https://example.com\".\n * Used for canonical link, og:url fallback.\n */\n baseUrl?: string\n\n /**\n * Current page path, e.g. \"/about\".\n * Defaults to \"\".\n */\n path?: string\n\n /**\n * Default values used when SEO fields are missing.\n */\n defaults?: BuildSeoMetaOptions['defaults']\n\n /**\n * Resolve a Sanity image asset reference to a full URL string.\n *\n * @example\n * imageUrlResolver={(img) => urlFor(img).width(1200).url()}\n */\n imageUrlResolver?: (image: SanityImage | SanityImageWithAlt) => string | null | undefined\n}\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\n/**\n * Renders all SEO meta tags for a page as plain React elements.\n * Intended to be placed inside your framework's <Head> / <head> component.\n *\n * Renders:\n * - `<title>`\n * - `<meta name=\"description\">`\n * - `<meta name=\"keywords\">`\n * - `<meta name=\"robots\">`\n * - OpenGraph meta tags (`og:*`)\n * - Twitter Card meta tags (`twitter:*`)\n * - Any custom `seo.metaAttributes` as `<meta name=\"...\" content=\"...\">`\n */\nexport function SeoMetaTags({\n data,\n baseUrl,\n path,\n defaults,\n imageUrlResolver,\n}: SeoMetaTagsProps): JSX.Element {\n const meta = buildSeoMeta({seo: data, baseUrl, path, defaults, imageUrlResolver})\n\n const robotsContent = [\n meta.robots?.index === false ? 'noindex' : 'index',\n meta.robots?.follow === false ? 'nofollow' : 'follow',\n meta.robots?.notranslate ? 'notranslate' : null,\n meta.robots?.noimageindex ? 'noimageindex' : null,\n ]\n .filter(Boolean)\n .join(', ')\n\n return (\n <>\n {/* ── Title ── */}\n {meta.title && <title>{meta.title}</title>}\n\n {/* ── Basic meta ── */}\n {meta.description && <meta name=\"description\" content={meta.description} />}\n {meta.keywords?.length ? <meta name=\"keywords\" content={meta.keywords.join(', ')} /> : null}\n <meta name=\"robots\" content={robotsContent} />\n <meta name=\"googlebot\" content={robotsContent} />\n\n {/* ── Open Graph ── */}\n {meta.openGraph?.type && <meta property=\"og:type\" content={meta.openGraph.type} />}\n {meta.openGraph?.url && <meta property=\"og:url\" content={meta.openGraph.url} />}\n {meta.openGraph?.title && <meta property=\"og:title\" content={meta.openGraph.title} />}\n {meta.openGraph?.description && (\n <meta property=\"og:description\" content={meta.openGraph.description} />\n )}\n {meta.openGraph?.siteName && (\n <meta property=\"og:site_name\" content={meta.openGraph.siteName} />\n )}\n {meta.openGraph?.images?.map((img, i) => (\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={`og-img-${i}`}>\n <meta property=\"og:image\" content={img.url} />\n {img.width && <meta property=\"og:image:width\" content={String(img.width)} />}\n {img.height && <meta property=\"og:image:height\" content={String(img.height)} />}\n {img.alt && <meta property=\"og:image:alt\" content={img.alt} />}\n </Fragment>\n ))}\n\n {/* ── Twitter Card ── */}\n {meta.twitter?.card && <meta name=\"twitter:card\" content={meta.twitter.card} />}\n {meta.twitter?.site && <meta name=\"twitter:site\" content={meta.twitter.site} />}\n {meta.twitter?.creator && <meta name=\"twitter:creator\" content={meta.twitter.creator} />}\n {meta.twitter?.title && <meta name=\"twitter:title\" content={meta.twitter.title} />}\n {meta.twitter?.description && (\n <meta name=\"twitter:description\" content={meta.twitter.description} />\n )}\n {meta.twitter?.images?.map((url, i) => (\n <meta key={`tw-img-${i}`} name=\"twitter:image\" content={url} />\n ))}\n\n {/* ── Custom meta attributes ── */}\n {meta.other &&\n Object.entries(meta.other).map(([name, content]) => (\n <meta key={`custom-${name}`} name={name} content={content} />\n ))}\n\n {/* ── Canonical URL ── */}\n {meta.alternates?.canonical && <link rel=\"canonical\" href={meta.alternates.canonical} />}\n </>\n )\n}\n\nexport default SeoMetaTags\n"],"mappings":"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","names":["Fragment"]}
@@ -1,8 +1,40 @@
1
1
  import * as sanity from 'sanity';
2
+ import { a as HreflangTranslation } from './hreflang-_VbSuWYD.cjs';
2
3
  import { ComponentType } from 'react';
3
4
  import { D as DocumentWithSeoHealth } from './types-DxlPXihz.cjs';
4
5
 
6
+ type SeoGenField = 'title' | 'description' | 'focusKeyword' | 'keywords' | 'ogTitle' | 'ogDescription' | 'twitterTitle' | 'twitterDescription';
7
+ type MetaContext = {
8
+ title?: string;
9
+ description?: string;
10
+ slug?: string;
11
+ };
12
+
13
+ /** Auto-populate configuration for the `hreflangs` field. */
14
+ interface HreflangConfig {
15
+ /** Show the "Sync from translations" button on the hreflangs field. */
16
+ autoFill?: boolean;
17
+ /** Field holding the language tag on translated documents. Defaults to 'language'. */
18
+ localeField?: string;
19
+ /** Build the path for a translation. Defaults to `/${slug}`. */
20
+ resolvePath?: (t: HreflangTranslation) => string;
21
+ }
5
22
  type AiIndustry = 'blog' | 'ecommerce' | 'healthcare' | 'pharmacy' | 'saas' | 'finance' | 'realestate' | 'education' | 'restaurant' | 'travel' | 'fitness' | 'hospitality' | 'nonprofit' | 'legal' | 'insurance' | 'automotive' | 'homeServices';
23
+ /**
24
+ * All the generic document values the plugin extracts, handed to a custom prompt function so you can
25
+ * template your own prompt exactly the way the built-in prompts are built. `content` is the extracted
26
+ * document text (same output as the plugin's own content extraction).
27
+ */
28
+ type CustomPromptValues = {
29
+ field: SeoGenField;
30
+ content: string;
31
+ focusKeyword: string;
32
+ keywords: string[];
33
+ meta?: MetaContext;
34
+ industry?: AiIndustry;
35
+ };
36
+ /** Receives all generic document values, returns the prompt string sent to the AI provider. */
37
+ type CustomPromptFn = (values: CustomPromptValues) => string;
6
38
  interface AiConfig {
7
39
  /** AI provider to use for text generation. */
8
40
  provider?: 'openai' | 'anthropic' | 'groq' | 'gemini' | 'ollama';
@@ -48,6 +80,31 @@ interface AiConfig {
48
80
  content?: string | string[] | Record<string, string | string[]>;
49
81
  /** Industry context for prompts. When set, uses domain-specific vocabulary. Omit for generic prompts. */
50
82
  industry?: AiIndustry;
83
+ /**
84
+ * FREE tier: a single custom prompt (generic or industry-specific — the function decides based on the
85
+ * `field`/`industry` it receives). Ignored if `customPrompts` is also set.
86
+ *
87
+ * In proxy mode (`endpoint`), custom prompts must be set on the **server** handler config
88
+ * (`createSeoAiHandler`) — a function cannot be sent over HTTP.
89
+ *
90
+ * @example
91
+ * customPrompt: (v) => `Write a 55-char SEO ${v.field} about: ${v.content.slice(0, 200)}`
92
+ */
93
+ customPrompt?: CustomPromptFn;
94
+ /**
95
+ * PAID tier: up to 5 generic + up to 5 per-industry custom prompts. The count and per-industry
96
+ * pools are unlocked only behind a validated license via `seofields-pro`; without a valid license
97
+ * this collapses to a single prompt (same as the free `customPrompt`).
98
+ *
99
+ * By default custom prompts **replace** the built-in angle pool for a field. Set `merge: true` to
100
+ * mix them into the built-in pool instead.
101
+ */
102
+ customPrompts?: {
103
+ generic?: CustomPromptFn[];
104
+ byIndustry?: Partial<Record<AiIndustry, CustomPromptFn[]>>;
105
+ /** Mix custom prompts with the built-in angle pool. Default false = replace. */
106
+ merge?: boolean;
107
+ };
51
108
  /** Enable test mode — uses static pre-written outputs without any API call. Shows test warning in UI. */
52
109
  testMode?: boolean;
53
110
  /** Number of full generation attempts before giving up. Defaults to 2. */
@@ -223,6 +280,16 @@ interface SeoFieldsPluginConfig {
223
280
  * @example '2024-01-01'
224
281
  */
225
282
  apiVersion?: string;
283
+ /**
284
+ * Auto-populate the `hreflangs` field from document translations. Designed for
285
+ * `@sanity/document-internationalization` — adds a "Sync from translations" button to the field
286
+ * that reads the `translation.metadata` references and fills alternate entries (still editable).
287
+ * URLs are built from the root `baseUrl` + each translation's slug.
288
+ *
289
+ * @example
290
+ * hreflang: { autoFill: true, resolvePath: (t) => `/${t.language}/${t.slug}` }
291
+ */
292
+ hreflang?: HreflangConfig;
226
293
  /**
227
294
  * Enable or configure the SEO Health Dashboard tool.
228
295
  * If set to `true`, the dashboard is enabled with all defaults.
@@ -446,4 +513,4 @@ interface SeoFieldsPluginConfig {
446
513
  }
447
514
  declare const seofields: sanity.Plugin<void | SeoFieldsPluginConfig>;
448
515
 
449
- export { type AiConfig as A, type FieldVisibilityConfig as F, type PublishGateRequiredField as P, type SeoFieldsPluginConfig as S, type ValidHiddenFieldKeys as V, type AiIndustry as a, type AllFieldKeys as b, type SeoFieldConfig as c, type SeoFieldGroup as d, type SeoFieldKeys as e, type SeoObjectFieldName as f, type openGraphFieldKeys as o, seofields as s, type twitterFieldKeys as t };
516
+ export { type AiConfig as A, type CustomPromptFn as C, type FieldVisibilityConfig as F, type HreflangConfig as H, type MetaContext as M, type PublishGateRequiredField as P, type SeoGenField as S, type ValidHiddenFieldKeys as V, type AiIndustry as a, type SeoFieldsPluginConfig as b, type AllFieldKeys as c, type CustomPromptValues as d, type SeoFieldConfig as e, type SeoFieldGroup as f, type SeoFieldKeys as g, type SeoObjectFieldName as h, type openGraphFieldKeys as o, seofields as s, type twitterFieldKeys as t };
@@ -1,8 +1,40 @@
1
1
  import * as sanity from 'sanity';
2
+ import { a as HreflangTranslation } from './hreflang-_VbSuWYD.js';
2
3
  import { ComponentType } from 'react';
3
4
  import { D as DocumentWithSeoHealth } from './types-DxlPXihz.js';
4
5
 
6
+ type SeoGenField = 'title' | 'description' | 'focusKeyword' | 'keywords' | 'ogTitle' | 'ogDescription' | 'twitterTitle' | 'twitterDescription';
7
+ type MetaContext = {
8
+ title?: string;
9
+ description?: string;
10
+ slug?: string;
11
+ };
12
+
13
+ /** Auto-populate configuration for the `hreflangs` field. */
14
+ interface HreflangConfig {
15
+ /** Show the "Sync from translations" button on the hreflangs field. */
16
+ autoFill?: boolean;
17
+ /** Field holding the language tag on translated documents. Defaults to 'language'. */
18
+ localeField?: string;
19
+ /** Build the path for a translation. Defaults to `/${slug}`. */
20
+ resolvePath?: (t: HreflangTranslation) => string;
21
+ }
5
22
  type AiIndustry = 'blog' | 'ecommerce' | 'healthcare' | 'pharmacy' | 'saas' | 'finance' | 'realestate' | 'education' | 'restaurant' | 'travel' | 'fitness' | 'hospitality' | 'nonprofit' | 'legal' | 'insurance' | 'automotive' | 'homeServices';
23
+ /**
24
+ * All the generic document values the plugin extracts, handed to a custom prompt function so you can
25
+ * template your own prompt exactly the way the built-in prompts are built. `content` is the extracted
26
+ * document text (same output as the plugin's own content extraction).
27
+ */
28
+ type CustomPromptValues = {
29
+ field: SeoGenField;
30
+ content: string;
31
+ focusKeyword: string;
32
+ keywords: string[];
33
+ meta?: MetaContext;
34
+ industry?: AiIndustry;
35
+ };
36
+ /** Receives all generic document values, returns the prompt string sent to the AI provider. */
37
+ type CustomPromptFn = (values: CustomPromptValues) => string;
6
38
  interface AiConfig {
7
39
  /** AI provider to use for text generation. */
8
40
  provider?: 'openai' | 'anthropic' | 'groq' | 'gemini' | 'ollama';
@@ -48,6 +80,31 @@ interface AiConfig {
48
80
  content?: string | string[] | Record<string, string | string[]>;
49
81
  /** Industry context for prompts. When set, uses domain-specific vocabulary. Omit for generic prompts. */
50
82
  industry?: AiIndustry;
83
+ /**
84
+ * FREE tier: a single custom prompt (generic or industry-specific — the function decides based on the
85
+ * `field`/`industry` it receives). Ignored if `customPrompts` is also set.
86
+ *
87
+ * In proxy mode (`endpoint`), custom prompts must be set on the **server** handler config
88
+ * (`createSeoAiHandler`) — a function cannot be sent over HTTP.
89
+ *
90
+ * @example
91
+ * customPrompt: (v) => `Write a 55-char SEO ${v.field} about: ${v.content.slice(0, 200)}`
92
+ */
93
+ customPrompt?: CustomPromptFn;
94
+ /**
95
+ * PAID tier: up to 5 generic + up to 5 per-industry custom prompts. The count and per-industry
96
+ * pools are unlocked only behind a validated license via `seofields-pro`; without a valid license
97
+ * this collapses to a single prompt (same as the free `customPrompt`).
98
+ *
99
+ * By default custom prompts **replace** the built-in angle pool for a field. Set `merge: true` to
100
+ * mix them into the built-in pool instead.
101
+ */
102
+ customPrompts?: {
103
+ generic?: CustomPromptFn[];
104
+ byIndustry?: Partial<Record<AiIndustry, CustomPromptFn[]>>;
105
+ /** Mix custom prompts with the built-in angle pool. Default false = replace. */
106
+ merge?: boolean;
107
+ };
51
108
  /** Enable test mode — uses static pre-written outputs without any API call. Shows test warning in UI. */
52
109
  testMode?: boolean;
53
110
  /** Number of full generation attempts before giving up. Defaults to 2. */
@@ -223,6 +280,16 @@ interface SeoFieldsPluginConfig {
223
280
  * @example '2024-01-01'
224
281
  */
225
282
  apiVersion?: string;
283
+ /**
284
+ * Auto-populate the `hreflangs` field from document translations. Designed for
285
+ * `@sanity/document-internationalization` — adds a "Sync from translations" button to the field
286
+ * that reads the `translation.metadata` references and fills alternate entries (still editable).
287
+ * URLs are built from the root `baseUrl` + each translation's slug.
288
+ *
289
+ * @example
290
+ * hreflang: { autoFill: true, resolvePath: (t) => `/${t.language}/${t.slug}` }
291
+ */
292
+ hreflang?: HreflangConfig;
226
293
  /**
227
294
  * Enable or configure the SEO Health Dashboard tool.
228
295
  * If set to `true`, the dashboard is enabled with all defaults.
@@ -446,4 +513,4 @@ interface SeoFieldsPluginConfig {
446
513
  }
447
514
  declare const seofields: sanity.Plugin<void | SeoFieldsPluginConfig>;
448
515
 
449
- export { type AiConfig as A, type FieldVisibilityConfig as F, type PublishGateRequiredField as P, type SeoFieldsPluginConfig as S, type ValidHiddenFieldKeys as V, type AiIndustry as a, type AllFieldKeys as b, type SeoFieldConfig as c, type SeoFieldGroup as d, type SeoFieldKeys as e, type SeoObjectFieldName as f, type openGraphFieldKeys as o, seofields as s, type twitterFieldKeys as t };
516
+ export { type AiConfig as A, type CustomPromptFn as C, type FieldVisibilityConfig as F, type HreflangConfig as H, type MetaContext as M, type PublishGateRequiredField as P, type SeoGenField as S, type ValidHiddenFieldKeys as V, type AiIndustry as a, type SeoFieldsPluginConfig as b, type AllFieldKeys as c, type CustomPromptValues as d, type SeoFieldConfig as e, type SeoFieldGroup as f, type SeoFieldKeys as g, type SeoObjectFieldName as h, type openGraphFieldKeys as o, seofields as s, type twitterFieldKeys as t };
package/dist/server.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunk3OK3S2F7cjs = require('./chunk-3OK3S2F7.cjs');
3
+ var _chunkEUG4MNRCcjs = require('./chunk-EUG4MNRC.cjs');
4
4
 
5
5
 
6
6
 
@@ -23,7 +23,7 @@ function createSeoAiHandler(config) {
23
23
  industry: industry != null ? industry : config.industry,
24
24
  _licenseKey: licenseKey != null ? licenseKey : config._licenseKey
25
25
  });
26
- const result = await _chunk3OK3S2F7cjs.generateSeoText.call(void 0, field, content, focusKeyword, keywords, {
26
+ const result = await _chunkEUG4MNRCcjs.generateSeoText.call(void 0, field, content, focusKeyword, keywords, {
27
27
  config: mergedConfig,
28
28
  meta
29
29
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/hardik/GITHUB/sanity-plugin-seofields/npm/dist/server.cjs","../src/server/aiHandler.ts","../src/server/adapters/express.ts","../src/server/adapters/fetch.ts","../src/server/adapters/nextjs.ts","../src/server/adapters/node.ts"],"names":[],"mappings":"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","file":"/Users/hardik/GITHUB/sanity-plugin-seofields/npm/dist/server.cjs","sourcesContent":[null,"import type {AiConfig, AiIndustry} from '../plugin'\nimport {generateSeoText} from '../utils/seoContentGen'\nimport type {MetaContext, SeoGenField} from '../utils/seoPrompts'\n\nexport interface SeoAiRequestBody {\n field: SeoGenField\n content: string\n focusKeyword?: string\n keywords?: string[]\n meta?: MetaContext\n /** Industry chosen in the Studio's `ai.industry` config — forwarded so proxy mode matches direct-provider mode. */\n industry?: AiIndustry\n /** License key forwarded from the Studio's `ai._licenseKey` — determines which prompt pool proxy mode uses. */\n licenseKey?: string\n}\n\nexport interface SeoAiHandler {\n (body: SeoAiRequestBody): Promise<{result: string}>\n}\n\nfunction isValidBody(body: unknown): body is SeoAiRequestBody {\n if (!body || typeof body !== 'object') return false\n const {field, content} = body as Record<string, unknown>\n return typeof field === 'string' && typeof content === 'string'\n}\n\n/**\n * Runs the full SEO text generation pipeline (prompting, retries, validation) server-side using\n * a real `AiConfig` — including `apiKey` — which never has to be sent to the browser. Pair with\n * `endpoint` in the Studio's `ai` config, and one of the framework adapters in\n * `sanity-plugin-seofields/server` to expose it over HTTP.\n */\nexport function createSeoAiHandler(config: AiConfig): SeoAiHandler {\n return async function handleSeoAiRequest(body: SeoAiRequestBody): Promise<{result: string}> {\n if (!isValidBody(body)) {\n throw new Error('Invalid request body: \"field\" and \"content\" are required.')\n }\n\n const {field, content, focusKeyword = '', keywords = [], meta, industry, licenseKey} = body\n const mergedConfig: AiConfig = {\n ...config,\n industry: industry ?? config.industry,\n _licenseKey: licenseKey ?? config._licenseKey,\n }\n const result = await generateSeoText(field, content, focusKeyword, keywords, {\n config: mergedConfig,\n meta,\n })\n return {result}\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\n// Duck-typed instead of importing `express` types, so the package has no dependency on Express.\nexport interface MinimalRequest {\n method?: string\n body?: unknown\n}\n\nexport interface MinimalResponse {\n status(code: number): MinimalResponse\n json(body: unknown): void\n setHeader(name: string, value: string): void\n end(): void\n}\n\nexport interface ExpressAdapterOptions {\n cors?: string\n}\n\n/**\n * Express (or Express-compatible) request handler. Requires a JSON body parser\n * (e.g. `app.use(express.json())`) mounted before this route.\n *\n * @example\n * import { createExpressHandler } from 'sanity-plugin-seofields/server'\n * app.post('/api/seo-ai', createExpressHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY }))\n */\nexport function createExpressHandler(\n config: AiConfig,\n options: ExpressAdapterOptions = {},\n): (req: MinimalRequest, res: MinimalResponse) => Promise<void> {\n const handle = createSeoAiHandler(config)\n\n return async function seoAiExpressHandler(\n req: MinimalRequest,\n res: MinimalResponse,\n ): Promise<void> {\n if (options.cors) res.setHeader('Access-Control-Allow-Origin', options.cors)\n\n if (req.method === 'OPTIONS') {\n res.status(204).end()\n return\n }\n\n if (req.method !== 'POST') {\n res.status(405).json({error: 'Method not allowed'})\n return\n }\n\n try {\n const result = await handle(req.body as SeoAiRequestBody)\n res.status(200).json(result)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n res.status(500).json({error: message})\n }\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\nexport interface FetchAdapterOptions {\n /** Origin allowed to call this endpoint. Only needed when the proxy is deployed on a\n * different origin than the Studio (same-app routes don't hit CORS at all). */\n cors?: string\n}\n\nfunction corsHeaders(options: FetchAdapterOptions): Record<string, string> {\n return options.cors ? {'Access-Control-Allow-Origin': options.cors} : {}\n}\n\n/**\n * Standard `Request -> Response` handler. Works as-is for Next.js App Router route handlers,\n * Cloudflare Workers, Deno, Bun, Remix, and SvelteKit — anything built on the Fetch API.\n */\nexport function createFetchHandler(\n config: AiConfig,\n options: FetchAdapterOptions = {},\n): (request: Request) => Promise<Response> {\n const handle = createSeoAiHandler(config)\n const headers = {'Content-Type': 'application/json', ...corsHeaders(options)}\n\n return async function seoAiFetchHandler(request: Request): Promise<Response> {\n if (request.method === 'OPTIONS') {\n return new Response(null, {\n status: 204,\n headers: {\n ...headers,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n },\n })\n }\n\n if (request.method !== 'POST') {\n return new Response(JSON.stringify({error: 'Method not allowed'}), {status: 405, headers})\n }\n\n try {\n const body = (await request.json()) as SeoAiRequestBody\n const result = await handle(body)\n return new Response(JSON.stringify(result), {status: 200, headers})\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n return new Response(JSON.stringify({error: message}), {status: 500, headers})\n }\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createFetchHandler, type FetchAdapterOptions} from './fetch'\n\n/**\n * Next.js App Router route handler.\n *\n * @example\n * // app/api/seo-ai/route.ts\n * import { createNextRouteHandler } from 'sanity-plugin-seofields/server'\n *\n * export const { POST, OPTIONS } = createNextRouteHandler({\n * provider: 'openai',\n * apiKey: process.env.OPENAI_API_KEY,\n * })\n */\nexport function createNextRouteHandler(\n config: AiConfig,\n options?: FetchAdapterOptions,\n): {\n POST: (request: Request) => Promise<Response>\n OPTIONS: (request: Request) => Promise<Response>\n} {\n const handler = createFetchHandler(config, options)\n return {POST: handler, OPTIONS: handler}\n}\n","import type {IncomingMessage, ServerResponse} from 'node:http'\n\nimport type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\nexport interface NodeAdapterOptions {\n cors?: string\n}\n\nasync function readJsonBody(req: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = []\n for await (const chunk of req) chunks.push(chunk as Buffer)\n const raw = Buffer.concat(chunks).toString('utf8')\n return raw ? JSON.parse(raw) : {}\n}\n\n/**\n * Raw Node `http`/`https` request handler.\n *\n * @example\n * import { createServer } from 'node:http'\n * import { createNodeHandler } from 'sanity-plugin-seofields/server'\n * createServer(createNodeHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY })).listen(3000)\n */\nexport function createNodeHandler(\n config: AiConfig,\n options: NodeAdapterOptions = {},\n): (req: IncomingMessage, res: ServerResponse) => Promise<void> {\n const handle = createSeoAiHandler(config)\n\n return async function seoAiNodeHandler(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (options.cors) res.setHeader('Access-Control-Allow-Origin', options.cors)\n res.setHeader('Content-Type', 'application/json')\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204)\n res.end()\n return\n }\n\n if (req.method !== 'POST') {\n res.writeHead(405)\n res.end(JSON.stringify({error: 'Method not allowed'}))\n return\n }\n\n try {\n const body = (await readJsonBody(req)) as SeoAiRequestBody\n const result = await handle(body)\n res.writeHead(200)\n res.end(JSON.stringify(result))\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n res.writeHead(500)\n res.end(JSON.stringify({error: message}))\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["/Users/hardik/GITHUB/sanity-plugin-seofields/npm/dist/server.cjs","../src/server/aiHandler.ts","../src/server/adapters/express.ts","../src/server/adapters/fetch.ts","../src/server/adapters/nextjs.ts","../src/server/adapters/node.ts"],"names":[],"mappings":"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","file":"/Users/hardik/GITHUB/sanity-plugin-seofields/npm/dist/server.cjs","sourcesContent":[null,"import type {AiConfig, AiIndustry} from '../plugin'\nimport {generateSeoText} from '../utils/seoContentGen'\nimport type {MetaContext, SeoGenField} from '../utils/seoPrompts'\n\nexport interface SeoAiRequestBody {\n field: SeoGenField\n content: string\n focusKeyword?: string\n keywords?: string[]\n meta?: MetaContext\n /** Industry chosen in the Studio's `ai.industry` config — forwarded so proxy mode matches direct-provider mode. */\n industry?: AiIndustry\n /** License key forwarded from the Studio's `ai._licenseKey` — determines which prompt pool proxy mode uses. */\n licenseKey?: string\n}\n\nexport interface SeoAiHandler {\n (body: SeoAiRequestBody): Promise<{result: string}>\n}\n\nfunction isValidBody(body: unknown): body is SeoAiRequestBody {\n if (!body || typeof body !== 'object') return false\n const {field, content} = body as Record<string, unknown>\n return typeof field === 'string' && typeof content === 'string'\n}\n\n/**\n * Runs the full SEO text generation pipeline (prompting, retries, validation) server-side using\n * a real `AiConfig` — including `apiKey` — which never has to be sent to the browser. Pair with\n * `endpoint` in the Studio's `ai` config, and one of the framework adapters in\n * `sanity-plugin-seofields/server` to expose it over HTTP.\n *\n * NOTE: `customPrompt` / `customPrompts` are functions and cannot cross the HTTP boundary, so in\n * proxy mode they must be set on THIS server config (the `AiConfig` passed here), not on the Studio's\n * `ai` config. They apply automatically since this handler runs `generateSeoText` with `config`.\n */\nexport function createSeoAiHandler(config: AiConfig): SeoAiHandler {\n return async function handleSeoAiRequest(body: SeoAiRequestBody): Promise<{result: string}> {\n if (!isValidBody(body)) {\n throw new Error('Invalid request body: \"field\" and \"content\" are required.')\n }\n\n const {field, content, focusKeyword = '', keywords = [], meta, industry, licenseKey} = body\n const mergedConfig: AiConfig = {\n ...config,\n industry: industry ?? config.industry,\n _licenseKey: licenseKey ?? config._licenseKey,\n }\n const result = await generateSeoText(field, content, focusKeyword, keywords, {\n config: mergedConfig,\n meta,\n })\n return {result}\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\n// Duck-typed instead of importing `express` types, so the package has no dependency on Express.\nexport interface MinimalRequest {\n method?: string\n body?: unknown\n}\n\nexport interface MinimalResponse {\n status(code: number): MinimalResponse\n json(body: unknown): void\n setHeader(name: string, value: string): void\n end(): void\n}\n\nexport interface ExpressAdapterOptions {\n cors?: string\n}\n\n/**\n * Express (or Express-compatible) request handler. Requires a JSON body parser\n * (e.g. `app.use(express.json())`) mounted before this route.\n *\n * @example\n * import { createExpressHandler } from 'sanity-plugin-seofields/server'\n * app.post('/api/seo-ai', createExpressHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY }))\n */\nexport function createExpressHandler(\n config: AiConfig,\n options: ExpressAdapterOptions = {},\n): (req: MinimalRequest, res: MinimalResponse) => Promise<void> {\n const handle = createSeoAiHandler(config)\n\n return async function seoAiExpressHandler(\n req: MinimalRequest,\n res: MinimalResponse,\n ): Promise<void> {\n if (options.cors) res.setHeader('Access-Control-Allow-Origin', options.cors)\n\n if (req.method === 'OPTIONS') {\n res.status(204).end()\n return\n }\n\n if (req.method !== 'POST') {\n res.status(405).json({error: 'Method not allowed'})\n return\n }\n\n try {\n const result = await handle(req.body as SeoAiRequestBody)\n res.status(200).json(result)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n res.status(500).json({error: message})\n }\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\nexport interface FetchAdapterOptions {\n /** Origin allowed to call this endpoint. Only needed when the proxy is deployed on a\n * different origin than the Studio (same-app routes don't hit CORS at all). */\n cors?: string\n}\n\nfunction corsHeaders(options: FetchAdapterOptions): Record<string, string> {\n return options.cors ? {'Access-Control-Allow-Origin': options.cors} : {}\n}\n\n/**\n * Standard `Request -> Response` handler. Works as-is for Next.js App Router route handlers,\n * Cloudflare Workers, Deno, Bun, Remix, and SvelteKit — anything built on the Fetch API.\n */\nexport function createFetchHandler(\n config: AiConfig,\n options: FetchAdapterOptions = {},\n): (request: Request) => Promise<Response> {\n const handle = createSeoAiHandler(config)\n const headers = {'Content-Type': 'application/json', ...corsHeaders(options)}\n\n return async function seoAiFetchHandler(request: Request): Promise<Response> {\n if (request.method === 'OPTIONS') {\n return new Response(null, {\n status: 204,\n headers: {\n ...headers,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n },\n })\n }\n\n if (request.method !== 'POST') {\n return new Response(JSON.stringify({error: 'Method not allowed'}), {status: 405, headers})\n }\n\n try {\n const body = (await request.json()) as SeoAiRequestBody\n const result = await handle(body)\n return new Response(JSON.stringify(result), {status: 200, headers})\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n return new Response(JSON.stringify({error: message}), {status: 500, headers})\n }\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createFetchHandler, type FetchAdapterOptions} from './fetch'\n\n/**\n * Next.js App Router route handler.\n *\n * @example\n * // app/api/seo-ai/route.ts\n * import { createNextRouteHandler } from 'sanity-plugin-seofields/server'\n *\n * export const { POST, OPTIONS } = createNextRouteHandler({\n * provider: 'openai',\n * apiKey: process.env.OPENAI_API_KEY,\n * })\n */\nexport function createNextRouteHandler(\n config: AiConfig,\n options?: FetchAdapterOptions,\n): {\n POST: (request: Request) => Promise<Response>\n OPTIONS: (request: Request) => Promise<Response>\n} {\n const handler = createFetchHandler(config, options)\n return {POST: handler, OPTIONS: handler}\n}\n","import type {IncomingMessage, ServerResponse} from 'node:http'\n\nimport type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\nexport interface NodeAdapterOptions {\n cors?: string\n}\n\nasync function readJsonBody(req: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = []\n for await (const chunk of req) chunks.push(chunk as Buffer)\n const raw = Buffer.concat(chunks).toString('utf8')\n return raw ? JSON.parse(raw) : {}\n}\n\n/**\n * Raw Node `http`/`https` request handler.\n *\n * @example\n * import { createServer } from 'node:http'\n * import { createNodeHandler } from 'sanity-plugin-seofields/server'\n * createServer(createNodeHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY })).listen(3000)\n */\nexport function createNodeHandler(\n config: AiConfig,\n options: NodeAdapterOptions = {},\n): (req: IncomingMessage, res: ServerResponse) => Promise<void> {\n const handle = createSeoAiHandler(config)\n\n return async function seoAiNodeHandler(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (options.cors) res.setHeader('Access-Control-Allow-Origin', options.cors)\n res.setHeader('Content-Type', 'application/json')\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204)\n res.end()\n return\n }\n\n if (req.method !== 'POST') {\n res.writeHead(405)\n res.end(JSON.stringify({error: 'Method not allowed'}))\n return\n }\n\n try {\n const body = (await readJsonBody(req)) as SeoAiRequestBody\n const result = await handle(body)\n res.writeHead(200)\n res.end(JSON.stringify(result))\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n res.writeHead(500)\n res.end(JSON.stringify({error: message}))\n }\n }\n}\n"]}
package/dist/server.d.cts CHANGED
@@ -1,6 +1,7 @@
1
- import { A as AiConfig, a as AiIndustry } from './plugin-DoGeZP79.cjs';
1
+ import { A as AiConfig, S as SeoGenField, M as MetaContext, a as AiIndustry } from './plugin-HFuWZsJu.cjs';
2
2
  import { IncomingMessage, ServerResponse } from 'node:http';
3
3
  import 'sanity';
4
+ import './hreflang-_VbSuWYD.cjs';
4
5
  import 'react';
5
6
  import './types-DxlPXihz.cjs';
6
7
 
@@ -68,13 +69,6 @@ interface NodeAdapterOptions {
68
69
  */
69
70
  declare function createNodeHandler(config: AiConfig, options?: NodeAdapterOptions): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
70
71
 
71
- type SeoGenField = 'title' | 'description' | 'focusKeyword' | 'keywords' | 'ogTitle' | 'ogDescription' | 'twitterTitle' | 'twitterDescription';
72
- type MetaContext = {
73
- title?: string;
74
- description?: string;
75
- slug?: string;
76
- };
77
-
78
72
  interface SeoAiRequestBody {
79
73
  field: SeoGenField;
80
74
  content: string;
@@ -96,6 +90,10 @@ interface SeoAiHandler {
96
90
  * a real `AiConfig` — including `apiKey` — which never has to be sent to the browser. Pair with
97
91
  * `endpoint` in the Studio's `ai` config, and one of the framework adapters in
98
92
  * `sanity-plugin-seofields/server` to expose it over HTTP.
93
+ *
94
+ * NOTE: `customPrompt` / `customPrompts` are functions and cannot cross the HTTP boundary, so in
95
+ * proxy mode they must be set on THIS server config (the `AiConfig` passed here), not on the Studio's
96
+ * `ai` config. They apply automatically since this handler runs `generateSeoText` with `config`.
99
97
  */
100
98
  declare function createSeoAiHandler(config: AiConfig): SeoAiHandler;
101
99
 
package/dist/server.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- import { A as AiConfig, a as AiIndustry } from './plugin-DQdThyxG.js';
1
+ import { A as AiConfig, S as SeoGenField, M as MetaContext, a as AiIndustry } from './plugin-oQUCim56.js';
2
2
  import { IncomingMessage, ServerResponse } from 'node:http';
3
3
  import 'sanity';
4
+ import './hreflang-_VbSuWYD.js';
4
5
  import 'react';
5
6
  import './types-DxlPXihz.js';
6
7
 
@@ -68,13 +69,6 @@ interface NodeAdapterOptions {
68
69
  */
69
70
  declare function createNodeHandler(config: AiConfig, options?: NodeAdapterOptions): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
70
71
 
71
- type SeoGenField = 'title' | 'description' | 'focusKeyword' | 'keywords' | 'ogTitle' | 'ogDescription' | 'twitterTitle' | 'twitterDescription';
72
- type MetaContext = {
73
- title?: string;
74
- description?: string;
75
- slug?: string;
76
- };
77
-
78
72
  interface SeoAiRequestBody {
79
73
  field: SeoGenField;
80
74
  content: string;
@@ -96,6 +90,10 @@ interface SeoAiHandler {
96
90
  * a real `AiConfig` — including `apiKey` — which never has to be sent to the browser. Pair with
97
91
  * `endpoint` in the Studio's `ai` config, and one of the framework adapters in
98
92
  * `sanity-plugin-seofields/server` to expose it over HTTP.
93
+ *
94
+ * NOTE: `customPrompt` / `customPrompts` are functions and cannot cross the HTTP boundary, so in
95
+ * proxy mode they must be set on THIS server config (the `AiConfig` passed here), not on the Studio's
96
+ * `ai` config. They apply automatically since this handler runs `generateSeoText` with `config`.
99
97
  */
100
98
  declare function createSeoAiHandler(config: AiConfig): SeoAiHandler;
101
99
 
package/dist/server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  generateSeoText
3
- } from "./chunk-Z5AOUU4H.js";
3
+ } from "./chunk-NLEB47UV.js";
4
4
  import {
5
5
  __forAwait,
6
6
  __spreadProps,