sanity-plugin-seofields 1.5.2 → 1.5.4
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.
- package/LICENSE +1 -1
- package/README.md +97 -1085
- package/dist/cli.js +1 -1
- package/dist/index.cjs +67 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +67 -1
- package/dist/index.js.map +1 -1
- package/dist/next.cjs +53 -33
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +39 -3
- package/dist/next.d.ts +39 -3
- package/dist/next.js +53 -33
- package/dist/next.js.map +1 -1
- package/package.json +18 -1
package/dist/next.cjs
CHANGED
|
@@ -33,24 +33,27 @@ function sanitizeTwitterCard(value) {
|
|
|
33
33
|
}
|
|
34
34
|
return "summary_large_image";
|
|
35
35
|
}
|
|
36
|
-
function
|
|
37
|
-
var _a, _b
|
|
38
|
-
const { seo, baseUrl = "", path = "", defaults = {}, imageUrlResolver } = options;
|
|
39
|
-
const normalizedBase = baseUrl.replace(/\/+$/, "");
|
|
40
|
-
const normalizedPath = path.replace(/^\/+/, "");
|
|
41
|
-
const fullUrl = [normalizedBase, normalizedPath].filter(Boolean).join("/");
|
|
42
|
-
let ogImageURL = defaults.ogImage || "";
|
|
36
|
+
function resolveOgImage(seo, defaults, imageUrlResolver) {
|
|
37
|
+
var _a, _b;
|
|
43
38
|
if (((_a = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _a.imageType) === "url" && seo.openGraph.imageUrl) {
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
39
|
+
return seo.openGraph.imageUrl;
|
|
40
|
+
}
|
|
41
|
+
if (((_b = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _b.image) && imageUrlResolver) {
|
|
42
|
+
return imageUrlResolver(seo.openGraph.image) || defaults.ogImage || "";
|
|
43
|
+
}
|
|
44
|
+
return defaults.ogImage || "";
|
|
45
|
+
}
|
|
46
|
+
function resolveTwitterImage(seo, ogImageURL, imageUrlResolver) {
|
|
47
|
+
var _a, _b;
|
|
48
|
+
if (((_a = seo == null ? void 0 : seo.twitter) == null ? void 0 : _a.imageType) === "url" && seo.twitter.imageUrl) {
|
|
49
|
+
return seo.twitter.imageUrl;
|
|
47
50
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
twitterImageURL = seo.twitter.imageUrl;
|
|
51
|
-
} else if (((_d = seo == null ? void 0 : seo.twitter) == null ? void 0 : _d.image) && imageUrlResolver) {
|
|
52
|
-
twitterImageURL = imageUrlResolver(seo.twitter.image) || twitterImageURL;
|
|
51
|
+
if (((_b = seo == null ? void 0 : seo.twitter) == null ? void 0 : _b.image) && imageUrlResolver) {
|
|
52
|
+
return imageUrlResolver(seo.twitter.image) || ogImageURL;
|
|
53
53
|
}
|
|
54
|
+
return ogImageURL;
|
|
55
|
+
}
|
|
56
|
+
function buildCustomMetaMap(seo) {
|
|
54
57
|
const other = {};
|
|
55
58
|
if (Array.isArray(seo == null ? void 0 : seo.metaAttributes)) {
|
|
56
59
|
for (const attr of seo.metaAttributes) {
|
|
@@ -59,33 +62,44 @@ function buildSeoMeta(options) {
|
|
|
59
62
|
}
|
|
60
63
|
}
|
|
61
64
|
}
|
|
62
|
-
|
|
65
|
+
return other;
|
|
66
|
+
}
|
|
67
|
+
function buildSeoMeta(options) {
|
|
68
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B;
|
|
69
|
+
const { seo, baseUrl = "", path = "", defaults = {}, imageUrlResolver } = options;
|
|
70
|
+
const normalizedBase = baseUrl.replace(/\/+$/, "");
|
|
71
|
+
const normalizedPath = path.replace(/^\/+/, "");
|
|
72
|
+
const fullUrl = [normalizedBase, normalizedPath].filter(Boolean).join("/");
|
|
73
|
+
const ogImageURL = resolveOgImage(seo, defaults, imageUrlResolver);
|
|
74
|
+
const twitterImageURL = resolveTwitterImage(seo, ogImageURL, imageUrlResolver);
|
|
75
|
+
const other = buildCustomMetaMap(seo);
|
|
76
|
+
const ogUrl = ((_a = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _a.url) || fullUrl;
|
|
63
77
|
return chunkS367Y35J_cjs.__spreadValues({
|
|
64
|
-
title: (
|
|
65
|
-
description: (
|
|
66
|
-
keywords: ((
|
|
78
|
+
title: (_c = (_b = seo == null ? void 0 : seo.title) != null ? _b : defaults.title) != null ? _c : null,
|
|
79
|
+
description: (_e = (_d = seo == null ? void 0 : seo.description) != null ? _d : defaults.description) != null ? _e : null,
|
|
80
|
+
keywords: ((_f = seo == null ? void 0 : seo.keywords) == null ? void 0 : _f.length) ? seo.keywords : void 0,
|
|
67
81
|
robots: {
|
|
68
|
-
index: !((
|
|
69
|
-
follow: !((
|
|
82
|
+
index: !((_g = seo == null ? void 0 : seo.robots) == null ? void 0 : _g.noIndex),
|
|
83
|
+
follow: !((_h = seo == null ? void 0 : seo.robots) == null ? void 0 : _h.noFollow),
|
|
70
84
|
googleBot: {
|
|
71
|
-
index: !((
|
|
72
|
-
follow: !((
|
|
85
|
+
index: !((_i = seo == null ? void 0 : seo.robots) == null ? void 0 : _i.noIndex),
|
|
86
|
+
follow: !((_j = seo == null ? void 0 : seo.robots) == null ? void 0 : _j.noFollow)
|
|
73
87
|
}
|
|
74
88
|
},
|
|
75
89
|
openGraph: {
|
|
76
|
-
type: sanitizeOGType((
|
|
90
|
+
type: sanitizeOGType((_l = (_k = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _k.type) != null ? _l : void 0),
|
|
77
91
|
url: ogUrl || void 0,
|
|
78
|
-
title: (
|
|
79
|
-
description: (
|
|
80
|
-
siteName: (
|
|
92
|
+
title: (_n = (_m = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _m.title) != null ? _n : defaults.title,
|
|
93
|
+
description: (_p = (_o = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _o.description) != null ? _p : defaults.description,
|
|
94
|
+
siteName: (_r = (_q = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _q.siteName) != null ? _r : defaults.siteName,
|
|
81
95
|
images: ogImageURL ? [{ url: ogImageURL }] : []
|
|
82
96
|
},
|
|
83
97
|
twitter: {
|
|
84
|
-
card: sanitizeTwitterCard((
|
|
85
|
-
site: (
|
|
86
|
-
creator: (
|
|
87
|
-
title: (
|
|
88
|
-
description: (
|
|
98
|
+
card: sanitizeTwitterCard((_t = (_s = seo == null ? void 0 : seo.twitter) == null ? void 0 : _s.card) != null ? _t : void 0),
|
|
99
|
+
site: (_v = (_u = seo == null ? void 0 : seo.twitter) == null ? void 0 : _u.site) != null ? _v : defaults.twitterSite,
|
|
100
|
+
creator: (_x = (_w = seo == null ? void 0 : seo.twitter) == null ? void 0 : _w.creator) != null ? _x : defaults.twitterCreator,
|
|
101
|
+
title: (_z = (_y = seo == null ? void 0 : seo.twitter) == null ? void 0 : _y.title) != null ? _z : defaults.title,
|
|
102
|
+
description: (_B = (_A = seo == null ? void 0 : seo.twitter) == null ? void 0 : _A.description) != null ? _B : defaults.description,
|
|
89
103
|
images: twitterImageURL ? [twitterImageURL] : []
|
|
90
104
|
},
|
|
91
105
|
alternates: {
|
|
@@ -93,7 +107,13 @@ function buildSeoMeta(options) {
|
|
|
93
107
|
}
|
|
94
108
|
}, Object.keys(other).length > 0 ? { other } : {});
|
|
95
109
|
}
|
|
96
|
-
function SeoMetaTags({
|
|
110
|
+
function SeoMetaTags({
|
|
111
|
+
data,
|
|
112
|
+
baseUrl,
|
|
113
|
+
path,
|
|
114
|
+
defaults,
|
|
115
|
+
imageUrlResolver
|
|
116
|
+
}) {
|
|
97
117
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
98
118
|
const meta = buildSeoMeta({ seo: data, baseUrl, path, defaults, imageUrlResolver });
|
|
99
119
|
const robotsContent = [
|
package/dist/next.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/helpers/seoMeta.ts","../src/helpers/SeoMetaTags.tsx"],"names":["__spreadValues","jsxs","Fragment","jsx","React"],"mappings":"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","file":"next.cjs","sourcesContent":["/**\n * Headless CMS integration helpers for sanity-plugin-seofields\n *\n * Provides framework-agnostic SEO metadata utilities for use with:\n * - Next.js App Router → buildSeoMeta() inside generateMetadata()\n * - Next.js Pages Router → <SeoMetaTags> inside Next.js <Head>\n * - Nuxt / Remix / any SSR → <SeoMetaTags> inside your <head> slot\n */\n\nimport type {SanityImage, SanityImageWithAlt, SeoFields} from '../types'\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Structured metadata returned by buildSeoMeta(). Compatible with Next.js Metadata (App Router). */\nexport interface SeoMetadata {\n title?: string | null\n description?: string | null\n keywords?: string[]\n robots?: {\n index?: boolean\n follow?: boolean\n googleBot?: {\n index?: boolean\n follow?: boolean\n }\n }\n openGraph?: {\n type?: string\n url?: string\n title?: string\n description?: string\n siteName?: string\n images?: Array<{url: string; width?: number; height?: number; alt?: string}>\n }\n twitter?: {\n card?: string\n site?: string\n creator?: string\n title?: string\n description?: string\n images?: string[]\n }\n alternates?: {\n canonical?: string\n }\n /** Any custom meta attributes from seo.metaAttributes */\n other?: Record<string, string>\n}\n\n/** Default values used when SEO fields are missing. */\nexport interface SeoMetaDefaults {\n title?: string\n description?: string\n siteName?: string\n twitterSite?: string\n twitterCreator?: string\n /** Fallback image URL when no OG / Twitter image is set. */\n ogImage?: string\n}\n\n/**\n * Permissive image shape accepted by buildSeoMeta — compatible with both the\n * plugin's SanityImage and Sanity's code-generated image type (where `asset`\n * and `alt` are optional).\n */\ninterface SeoImageInput {\n _type?: string\n asset?: {_ref: string; _type: string; _weak?: boolean; [key: string]: unknown}\n hotspot?: unknown\n crop?: unknown\n alt?: string\n}\n\n/**\n * Input-compatible variant of SeoFields. Structurally matches Sanity's\n * code-generated types (where `asset`, `alt`, `key`, and `type` are all\n * optional), so you can pass `data.seo` from a sanityFetch result directly\n * without any `as any` or manual casting.\n */\nexport interface SeoFieldsInput {\n _type?: string\n robots?: {noIndex?: boolean | null; noFollow?: boolean | null} | null\n title?: string | null\n description?: string | null\n metaImage?: SeoImageInput | null\n metaAttributes?: Array<{_key?: string; key?: string; value?: string; type?: string}> | null\n keywords?: string[] | null\n canonicalUrl?: string | null\n openGraph?: {\n _type?: string\n url?: string | null\n title?: string | null\n description?: string | null\n siteName?: string | null\n type?: string | null\n imageType?: string | null\n image?: SeoImageInput | null\n imageUrl?: string | null\n } | null\n twitter?: {\n _type?: string\n card?: string | null\n site?: string | null\n creator?: string | null\n title?: string | null\n description?: string | null\n imageType?: string | null\n image?: SeoImageInput | null\n imageUrl?: string | null\n } | null\n}\n\n/** Options accepted by buildSeoMeta(). */\nexport interface BuildSeoMetaOptions {\n /**\n * The raw SEO object from Sanity (_type excluded or included — both work).\n * Pass `null` or `undefined` to fall back entirely to `defaults`.\n *\n * Accepts both the strict plugin `SeoFields` type and Sanity's code-generated\n * type (which has all nested fields optional) without any `as any` cast.\n */\n seo?: SeoFieldsInput | null\n\n /**\n * The base URL of your site, e.g. \"https://example.com\".\n * Used for canonical URL and OpenGraph URL construction.\n */\n baseUrl?: string\n\n /**\n * The path for the current page, e.g. \"/about\".\n * Combined with baseUrl to produce the canonical + OG url.\n * Defaults to \"\".\n */\n path?: string\n\n /**\n * Default values used when the Sanity SEO fields are empty / missing.\n */\n defaults?: SeoMetaDefaults\n\n /**\n * Resolve a Sanity image asset to a plain URL string.\n *\n * @example (using @sanity/image-url)\n * imageUrlResolver: (img) => urlFor(img).width(1200).url()\n */\n imageUrlResolver?: (image: SanityImage | SanityImageWithAlt) => string | null | undefined\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nconst VALID_OG_TYPES = [\n 'website',\n 'article',\n 'profile',\n 'book',\n 'music',\n 'video',\n 'product',\n] as const\ntype OGType = (typeof VALID_OG_TYPES)[number]\n\n/**\n * Coerce an arbitrary string to a valid OpenGraph type.\n * Falls back to \"website\" when the value is invalid.\n */\nexport function sanitizeOGType(value?: string): OGType {\n if (value && (VALID_OG_TYPES as readonly string[]).includes(value)) {\n return value as OGType\n }\n return 'website'\n}\n\nconst VALID_TWITTER_CARDS = ['summary', 'summary_large_image', 'app', 'player'] as const\ntype TwitterCard = (typeof VALID_TWITTER_CARDS)[number]\n\n/**\n * Coerce an arbitrary string to a valid Twitter card type.\n * Falls back to \"summary_large_image\" when the value is invalid.\n */\nexport function sanitizeTwitterCard(value?: string): TwitterCard {\n if (value && (VALID_TWITTER_CARDS as readonly string[]).includes(value)) {\n return value as TwitterCard\n }\n return 'summary_large_image'\n}\n\n// ─── Core builder ─────────────────────────────────────────────────────────────\n\n/**\n * Convert a Sanity SEO object into a structured metadata object.\n *\n * The return value is structurally compatible with Next.js App Router's\n * `Metadata` type, so you can return it directly from `generateMetadata()`.\n *\n * @example Next.js App Router\n * ```ts\n * import { buildSeoMeta } from 'sanity-plugin-seofields'\n * import { urlFor } from '@/sanity/lib/image'\n *\n * export async function generateMetadata(): Promise<Metadata> {\n * const { seo } = await sanityFetch({ query: PAGE_SEO_QUERY })\n * return buildSeoMeta({\n * seo,\n * baseUrl: process.env.NEXT_PUBLIC_SITE_URL,\n * path: '/about',\n * defaults: { title: 'My Site', siteName: 'My Site' },\n * imageUrlResolver: (img) => urlFor(img).width(1200).url(),\n * })\n * }\n * ```\n */\nexport function buildSeoMeta(options: BuildSeoMetaOptions): SeoMetadata {\n const {seo, baseUrl = '', path = '', defaults = {}, imageUrlResolver} = options\n\n const normalizedBase = baseUrl.replace(/\\/+$/, '') // remove trailing /\n const normalizedPath = path.replace(/^\\/+/, '') // remove leading /\n\n const fullUrl = [normalizedBase, normalizedPath].filter(Boolean).join('/')\n\n // ── OG image resolution ──\n let ogImageURL: string = defaults.ogImage || ''\n if (seo?.openGraph?.imageType === 'url' && seo.openGraph.imageUrl) {\n ogImageURL = seo.openGraph.imageUrl\n } else if (seo?.openGraph?.image && imageUrlResolver) {\n ogImageURL = imageUrlResolver(seo.openGraph.image as SanityImage) || ogImageURL\n }\n\n // ── Twitter image resolution ──\n let twitterImageURL: string = ogImageURL // reuse OG image as fallback\n if (seo?.twitter?.imageType === 'url' && seo.twitter.imageUrl) {\n twitterImageURL = seo.twitter.imageUrl\n } else if (seo?.twitter?.image && imageUrlResolver) {\n twitterImageURL = imageUrlResolver(seo.twitter.image as SanityImage) || twitterImageURL\n }\n\n // ── Custom meta attributes → `other` map ──\n const other: Record<string, string> = {}\n if (Array.isArray(seo?.metaAttributes)) {\n for (const attr of seo!.metaAttributes!) {\n if (attr.key && attr.value) {\n other[attr.key] = attr.value\n }\n }\n }\n\n const ogUrl = seo?.openGraph?.url || fullUrl\n\n return {\n title: seo?.title ?? defaults.title ?? null,\n description: seo?.description ?? defaults.description ?? null,\n keywords: seo?.keywords?.length ? (seo.keywords as string[]) : undefined,\n robots: {\n index: !seo?.robots?.noIndex,\n follow: !seo?.robots?.noFollow,\n googleBot: {\n index: !seo?.robots?.noIndex,\n follow: !seo?.robots?.noFollow,\n },\n },\n openGraph: {\n type: sanitizeOGType(seo?.openGraph?.type ?? undefined),\n url: ogUrl || undefined,\n title: seo?.openGraph?.title ?? defaults.title,\n description: seo?.openGraph?.description ?? defaults.description,\n siteName: seo?.openGraph?.siteName ?? defaults.siteName,\n images: ogImageURL ? [{url: ogImageURL}] : [],\n },\n twitter: {\n card: sanitizeTwitterCard(seo?.twitter?.card ?? undefined),\n site: seo?.twitter?.site ?? defaults.twitterSite,\n creator: seo?.twitter?.creator ?? defaults.twitterCreator,\n title: seo?.twitter?.title ?? defaults.title,\n description: seo?.twitter?.description ?? defaults.description,\n images: twitterImageURL ? [twitterImageURL] : [],\n },\n alternates: {\n canonical: fullUrl || undefined,\n },\n ...(Object.keys(other).length > 0 ? {other} : {}),\n }\n}\n","/**\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'\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 Nuxt 3 / generic SSR (inside <Head> slot)\n * ```tsx\n * <Head>\n * <SeoMetaTags data={seo} baseUrl=\"https://example.com\" path=\"/\" />\n * </Head>\n * ```\n */\nimport React 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({data, baseUrl, path, defaults, imageUrlResolver}: SeoMetaTagsProps) {\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 ].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 <React.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 </React.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":["../src/helpers/seoMeta.ts","../src/helpers/SeoMetaTags.tsx"],"names":["__spreadValues","jsxs","Fragment","jsx","React"],"mappings":"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","file":"next.cjs","sourcesContent":["/**\n * Headless CMS integration helpers for sanity-plugin-seofields\n *\n * Provides framework-agnostic SEO metadata utilities for use with:\n * - Next.js App Router → buildSeoMeta() inside generateMetadata()\n * - Next.js Pages Router → <SeoMetaTags> inside Next.js <Head>\n * - Nuxt / Remix / any SSR → <SeoMetaTags> inside your <head> slot\n */\n\nimport type {SanityImage, SanityImageWithAlt} from '../types'\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/** Structured metadata returned by buildSeoMeta(). Compatible with Next.js Metadata (App Router). */\nexport interface SeoMetadata {\n title?: string | null\n description?: string | null\n keywords?: string[]\n robots?: {\n index?: boolean\n follow?: boolean\n googleBot?: {\n index?: boolean\n follow?: boolean\n }\n }\n openGraph?: {\n type?: string\n url?: string\n title?: string\n description?: string\n siteName?: string\n images?: Array<{url: string; width?: number; height?: number; alt?: string}>\n }\n twitter?: {\n card?: string\n site?: string\n creator?: string\n title?: string\n description?: string\n images?: string[]\n }\n alternates?: {\n canonical?: string\n }\n /** Any custom meta attributes from seo.metaAttributes */\n other?: Record<string, string>\n}\n\n/** Default values used when SEO fields are missing. */\nexport interface SeoMetaDefaults {\n title?: string\n description?: string\n siteName?: string\n twitterSite?: string\n twitterCreator?: string\n /** Fallback image URL when no OG / Twitter image is set. */\n ogImage?: string\n}\n\n/**\n * Permissive image shape accepted by buildSeoMeta — compatible with both the\n * plugin's SanityImage and Sanity's code-generated image type (where `asset`\n * and `alt` are optional).\n */\ninterface SeoImageInput {\n _type?: string\n asset?: {_ref: string; _type: string; _weak?: boolean; [key: string]: unknown}\n hotspot?: unknown\n crop?: unknown\n alt?: string\n}\n\n/**\n * Input-compatible variant of SeoFields. Structurally matches Sanity's\n * code-generated types (where `asset`, `alt`, `key`, and `type` are all\n * optional), so you can pass `data.seo` from a sanityFetch result directly\n * without any `as any` or manual casting.\n */\nexport interface SeoFieldsInput {\n _type?: string\n robots?: {noIndex?: boolean | null; noFollow?: boolean | null} | null\n title?: string | null\n description?: string | null\n metaImage?: SeoImageInput | null\n metaAttributes?: Array<{_key?: string; key?: string; value?: string; type?: string}> | null\n keywords?: string[] | null\n canonicalUrl?: string | null\n openGraph?: {\n _type?: string\n url?: string | null\n title?: string | null\n description?: string | null\n siteName?: string | null\n type?: string | null\n imageType?: string | null\n image?: SeoImageInput | null\n imageUrl?: string | null\n } | null\n twitter?: {\n _type?: string\n card?: string | null\n site?: string | null\n creator?: string | null\n title?: string | null\n description?: string | null\n imageType?: string | null\n image?: SeoImageInput | null\n imageUrl?: string | null\n } | null\n}\n\n/** Options accepted by buildSeoMeta(). */\nexport interface BuildSeoMetaOptions {\n /**\n * The raw SEO object from Sanity (_type excluded or included — both work).\n * Pass `null` or `undefined` to fall back entirely to `defaults`.\n *\n * Accepts both the strict plugin `SeoFields` type and Sanity's code-generated\n * type (which has all nested fields optional) without any `as any` cast.\n */\n seo?: SeoFieldsInput | null\n\n /**\n * The base URL of your site, e.g. \"https://example.com\".\n * Used for canonical URL and OpenGraph URL construction.\n */\n baseUrl?: string\n\n /**\n * The path for the current page, e.g. \"/about\".\n * Combined with baseUrl to produce the canonical + OG url.\n * Defaults to \"\".\n */\n path?: string\n\n /**\n * Default values used when the Sanity SEO fields are empty / missing.\n */\n defaults?: SeoMetaDefaults\n\n /**\n * Resolve a Sanity image asset to a plain URL string.\n *\n * @example (using @sanity/image-url)\n * imageUrlResolver: (img) => urlFor(img).width(1200).url()\n */\n imageUrlResolver?: (image: SanityImage | SanityImageWithAlt) => string | null | undefined\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nconst VALID_OG_TYPES = [\n 'website',\n 'article',\n 'profile',\n 'book',\n 'music',\n 'video',\n 'product',\n] as const\ntype OGType = (typeof VALID_OG_TYPES)[number]\n\n/**\n * Coerce an arbitrary string to a valid OpenGraph type.\n * Falls back to \"website\" when the value is invalid.\n */\nexport function sanitizeOGType(value?: string): OGType {\n if (value && (VALID_OG_TYPES as readonly string[]).includes(value)) {\n return value as OGType\n }\n return 'website'\n}\n\nconst VALID_TWITTER_CARDS = ['summary', 'summary_large_image', 'app', 'player'] as const\ntype TwitterCard = (typeof VALID_TWITTER_CARDS)[number]\n\n/**\n * Coerce an arbitrary string to a valid Twitter card type.\n * Falls back to \"summary_large_image\" when the value is invalid.\n */\nexport function sanitizeTwitterCard(value?: string): TwitterCard {\n if (value && (VALID_TWITTER_CARDS as readonly string[]).includes(value)) {\n return value as TwitterCard\n }\n return 'summary_large_image'\n}\n\n/**\n * Resolve OG image URL from SEO fields or defaults.\n */\nfunction resolveOgImage(\n seo: SeoFieldsInput | null | undefined,\n defaults: SeoMetaDefaults,\n imageUrlResolver?: (image: SanityImage | SanityImageWithAlt) => string | null | undefined,\n): string {\n if (seo?.openGraph?.imageType === 'url' && seo.openGraph.imageUrl) {\n return seo.openGraph.imageUrl\n }\n if (seo?.openGraph?.image && imageUrlResolver) {\n return imageUrlResolver(seo.openGraph.image as SanityImage) || defaults.ogImage || ''\n }\n return defaults.ogImage || ''\n}\n\n/**\n * Resolve Twitter image URL from SEO fields, falling back to OG image.\n */\nfunction resolveTwitterImage(\n seo: SeoFieldsInput | null | undefined,\n ogImageURL: string,\n imageUrlResolver?: (image: SanityImage | SanityImageWithAlt) => string | null | undefined,\n): string {\n if (seo?.twitter?.imageType === 'url' && seo.twitter.imageUrl) {\n return seo.twitter.imageUrl\n }\n if (seo?.twitter?.image && imageUrlResolver) {\n return imageUrlResolver(seo.twitter.image as SanityImage) || ogImageURL\n }\n return ogImageURL\n}\n\n/**\n * Build custom meta attributes map from SEO fields.\n */\nfunction buildCustomMetaMap(seo: SeoFieldsInput | null | undefined): Record<string, string> {\n const other: Record<string, string> = {}\n if (Array.isArray(seo?.metaAttributes)) {\n for (const attr of seo!.metaAttributes!) {\n if (attr.key && attr.value) {\n other[attr.key] = attr.value\n }\n }\n }\n return other\n}\n\n// ─── Core builder ─────────────────────────────────────────────────────────────\n\n/**\n * Convert a Sanity SEO object into a structured metadata object.\n *\n * The return value is structurally compatible with Next.js App Router's\n * `Metadata` type, so you can return it directly from `generateMetadata()`.\n *\n * @example Next.js App Router\n * ```ts\n * import { buildSeoMeta } from 'sanity-plugin-seofields'\n * import { urlFor } from '@/sanity/lib/image'\n *\n * export async function generateMetadata(): Promise<Metadata> {\n * const { seo } = await sanityFetch({ query: PAGE_SEO_QUERY })\n * return buildSeoMeta({\n * seo,\n * baseUrl: process.env.NEXT_PUBLIC_SITE_URL,\n * path: '/about',\n * defaults: { title: 'My Site', siteName: 'My Site' },\n * imageUrlResolver: (img) => urlFor(img).width(1200).url(),\n * })\n * }\n * ```\n */\nexport function buildSeoMeta(options: BuildSeoMetaOptions): SeoMetadata {\n const {seo, baseUrl = '', path = '', defaults = {}, imageUrlResolver} = options\n\n const normalizedBase = baseUrl.replace(/\\/+$/, '') // remove trailing /\n const normalizedPath = path.replace(/^\\/+/, '') // remove leading /\n\n const fullUrl = [normalizedBase, normalizedPath].filter(Boolean).join('/')\n\n const ogImageURL = resolveOgImage(seo, defaults, imageUrlResolver)\n const twitterImageURL = resolveTwitterImage(seo, ogImageURL, imageUrlResolver)\n const other = buildCustomMetaMap(seo)\n\n const ogUrl = seo?.openGraph?.url || fullUrl\n\n return {\n title: seo?.title ?? defaults.title ?? null,\n description: seo?.description ?? defaults.description ?? null,\n keywords: seo?.keywords?.length ? (seo.keywords as string[]) : undefined,\n robots: {\n index: !seo?.robots?.noIndex,\n follow: !seo?.robots?.noFollow,\n googleBot: {\n index: !seo?.robots?.noIndex,\n follow: !seo?.robots?.noFollow,\n },\n },\n openGraph: {\n type: sanitizeOGType(seo?.openGraph?.type ?? undefined),\n url: ogUrl || undefined,\n title: seo?.openGraph?.title ?? defaults.title,\n description: seo?.openGraph?.description ?? defaults.description,\n siteName: seo?.openGraph?.siteName ?? defaults.siteName,\n images: ogImageURL ? [{url: ogImageURL}] : [],\n },\n twitter: {\n card: sanitizeTwitterCard(seo?.twitter?.card ?? undefined),\n site: seo?.twitter?.site ?? defaults.twitterSite,\n creator: seo?.twitter?.creator ?? defaults.twitterCreator,\n title: seo?.twitter?.title ?? defaults.title,\n description: seo?.twitter?.description ?? defaults.description,\n images: twitterImageURL ? [twitterImageURL] : [],\n },\n alternates: {\n canonical: fullUrl || undefined,\n },\n ...(Object.keys(other).length > 0 ? {other} : {}),\n }\n}\n","/**\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'\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 Nuxt 3 / generic SSR (inside <Head> slot)\n * ```tsx\n * <Head>\n * <SeoMetaTags data={seo} baseUrl=\"https://example.com\" path=\"/\" />\n * </Head>\n * ```\n */\nimport React 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): React.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 ].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 <React.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 </React.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,6 @@
|
|
|
1
1
|
import { S as SanityImage, a as SanityImageWithAlt, b as SeoFields } from './types-R3n9Fu4w.cjs';
|
|
2
|
-
import
|
|
2
|
+
import React from 'react';
|
|
3
3
|
export { AggregateRatingSchema, AggregateRatingSchemaProps, ArticleSchema, ArticleSchemaProps, BlogPostingSchema, BlogPostingSchemaProps, BrandSchema, BrandSchemaProps, BreadcrumbListSchema, BreadcrumbListSchemaProps, ContactPointSchema, ContactPointSchemaProps, CourseSchema, CourseSchemaProps, EventSchema, EventSchemaProps, FAQPageSchema, FAQPageSchemaProps, HowToSchema, HowToSchemaProps, ImageObjectSchema, ImageObjectSchemaProps, LocalBusinessSchema, LocalBusinessSchemaProps, OfferSchema, OfferSchemaProps, OrganizationSchema, OrganizationSchemaProps, PersonSchema, PersonSchemaProps, PlaceSchema, PlaceSchemaProps, PostalAddressSchema, PostalAddressSchemaProps, ProductSchema, ProductSchemaProps, ReviewSchema, ReviewSchemaProps, SchemaOrgScripts, SchemaOrgScriptsProps, SoftwareApplicationSchema, SoftwareApplicationSchemaProps, VideoObjectSchema, VideoObjectSchemaProps, WebApplicationSchema, WebApplicationSchemaProps, WebPageSchema, WebPageSchemaProps, WebsiteSchema, WebsiteSchemaProps, buildAggregateRatingJsonLd, buildArticleJsonLd, buildBlogPostingJsonLd, buildBrandJsonLd, buildBreadcrumbListJsonLd, buildContactPointJsonLd, buildCourseJsonLd, buildEventJsonLd, buildFAQPageJsonLd, buildHowToJsonLd, buildImageObjectJsonLd, buildLocalBusinessJsonLd, buildOfferJsonLd, buildOrganizationJsonLd, buildPersonJsonLd, buildPlaceJsonLd, buildPostalAddressJsonLd, buildProductJsonLd, buildReviewJsonLd, buildSoftwareApplicationJsonLd, buildVideoObjectJsonLd, buildWebApplicationJsonLd, buildWebPageJsonLd, buildWebsiteJsonLd } from './schema/next.cjs';
|
|
4
|
-
import 'react';
|
|
5
4
|
import './types-CVaAX7uy.cjs';
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -198,6 +197,43 @@ declare function sanitizeTwitterCard(value?: string): TwitterCard;
|
|
|
198
197
|
*/
|
|
199
198
|
declare function buildSeoMeta(options: BuildSeoMetaOptions): SeoMetadata;
|
|
200
199
|
|
|
200
|
+
/**
|
|
201
|
+
* <SeoMetaTags> — Framework-agnostic React SEO meta tag renderer.
|
|
202
|
+
*
|
|
203
|
+
* Renders all SEO meta tags as plain React elements.
|
|
204
|
+
* Place it inside your framework's <Head> component:
|
|
205
|
+
*
|
|
206
|
+
* @example Next.js Pages Router
|
|
207
|
+
* ```tsx
|
|
208
|
+
* import Head from 'next/head'
|
|
209
|
+
* import { SeoMetaTags } from 'sanity-plugin-seofields'
|
|
210
|
+
*
|
|
211
|
+
* export default function Page({ seo }) {
|
|
212
|
+
* return (
|
|
213
|
+
* <>
|
|
214
|
+
* <Head>
|
|
215
|
+
* <SeoMetaTags
|
|
216
|
+
* data={seo}
|
|
217
|
+
* baseUrl="https://example.com"
|
|
218
|
+
* path="/about"
|
|
219
|
+
* defaults={{ title: 'My Site', siteName: 'My Site' }}
|
|
220
|
+
* imageUrlResolver={(img) => urlFor(img).width(1200).url()}
|
|
221
|
+
* />
|
|
222
|
+
* </Head>
|
|
223
|
+
* <main>...</main>
|
|
224
|
+
* </>
|
|
225
|
+
* )
|
|
226
|
+
* }
|
|
227
|
+
* ```
|
|
228
|
+
*
|
|
229
|
+
* @example Nuxt 3 / generic SSR (inside <Head> slot)
|
|
230
|
+
* ```tsx
|
|
231
|
+
* <Head>
|
|
232
|
+
* <SeoMetaTags data={seo} baseUrl="https://example.com" path="/" />
|
|
233
|
+
* </Head>
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
|
|
201
237
|
interface SeoMetaTagsProps {
|
|
202
238
|
/**
|
|
203
239
|
* The raw SEO object from Sanity.
|
|
@@ -239,6 +275,6 @@ interface SeoMetaTagsProps {
|
|
|
239
275
|
* - Twitter Card meta tags (`twitter:*`)
|
|
240
276
|
* - Any custom `seo.metaAttributes` as `<meta name="..." content="...">`
|
|
241
277
|
*/
|
|
242
|
-
declare function SeoMetaTags({ data, baseUrl, path, defaults, imageUrlResolver }: SeoMetaTagsProps):
|
|
278
|
+
declare function SeoMetaTags({ data, baseUrl, path, defaults, imageUrlResolver, }: SeoMetaTagsProps): React.JSX.Element;
|
|
243
279
|
|
|
244
280
|
export { type BuildSeoMetaOptions, type SeoFieldsInput, type SeoMetaDefaults, SeoMetaTags, type SeoMetaTagsProps, type SeoMetadata, buildSeoMeta, sanitizeOGType, sanitizeTwitterCard };
|
package/dist/next.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { S as SanityImage, a as SanityImageWithAlt, b as SeoFields } from './types-R3n9Fu4w.js';
|
|
2
|
-
import
|
|
2
|
+
import React from 'react';
|
|
3
3
|
export { AggregateRatingSchema, AggregateRatingSchemaProps, ArticleSchema, ArticleSchemaProps, BlogPostingSchema, BlogPostingSchemaProps, BrandSchema, BrandSchemaProps, BreadcrumbListSchema, BreadcrumbListSchemaProps, ContactPointSchema, ContactPointSchemaProps, CourseSchema, CourseSchemaProps, EventSchema, EventSchemaProps, FAQPageSchema, FAQPageSchemaProps, HowToSchema, HowToSchemaProps, ImageObjectSchema, ImageObjectSchemaProps, LocalBusinessSchema, LocalBusinessSchemaProps, OfferSchema, OfferSchemaProps, OrganizationSchema, OrganizationSchemaProps, PersonSchema, PersonSchemaProps, PlaceSchema, PlaceSchemaProps, PostalAddressSchema, PostalAddressSchemaProps, ProductSchema, ProductSchemaProps, ReviewSchema, ReviewSchemaProps, SchemaOrgScripts, SchemaOrgScriptsProps, SoftwareApplicationSchema, SoftwareApplicationSchemaProps, VideoObjectSchema, VideoObjectSchemaProps, WebApplicationSchema, WebApplicationSchemaProps, WebPageSchema, WebPageSchemaProps, WebsiteSchema, WebsiteSchemaProps, buildAggregateRatingJsonLd, buildArticleJsonLd, buildBlogPostingJsonLd, buildBrandJsonLd, buildBreadcrumbListJsonLd, buildContactPointJsonLd, buildCourseJsonLd, buildEventJsonLd, buildFAQPageJsonLd, buildHowToJsonLd, buildImageObjectJsonLd, buildLocalBusinessJsonLd, buildOfferJsonLd, buildOrganizationJsonLd, buildPersonJsonLd, buildPlaceJsonLd, buildPostalAddressJsonLd, buildProductJsonLd, buildReviewJsonLd, buildSoftwareApplicationJsonLd, buildVideoObjectJsonLd, buildWebApplicationJsonLd, buildWebPageJsonLd, buildWebsiteJsonLd } from './schema/next.js';
|
|
4
|
-
import 'react';
|
|
5
4
|
import './types-Ci-ZZT7A.js';
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -198,6 +197,43 @@ declare function sanitizeTwitterCard(value?: string): TwitterCard;
|
|
|
198
197
|
*/
|
|
199
198
|
declare function buildSeoMeta(options: BuildSeoMetaOptions): SeoMetadata;
|
|
200
199
|
|
|
200
|
+
/**
|
|
201
|
+
* <SeoMetaTags> — Framework-agnostic React SEO meta tag renderer.
|
|
202
|
+
*
|
|
203
|
+
* Renders all SEO meta tags as plain React elements.
|
|
204
|
+
* Place it inside your framework's <Head> component:
|
|
205
|
+
*
|
|
206
|
+
* @example Next.js Pages Router
|
|
207
|
+
* ```tsx
|
|
208
|
+
* import Head from 'next/head'
|
|
209
|
+
* import { SeoMetaTags } from 'sanity-plugin-seofields'
|
|
210
|
+
*
|
|
211
|
+
* export default function Page({ seo }) {
|
|
212
|
+
* return (
|
|
213
|
+
* <>
|
|
214
|
+
* <Head>
|
|
215
|
+
* <SeoMetaTags
|
|
216
|
+
* data={seo}
|
|
217
|
+
* baseUrl="https://example.com"
|
|
218
|
+
* path="/about"
|
|
219
|
+
* defaults={{ title: 'My Site', siteName: 'My Site' }}
|
|
220
|
+
* imageUrlResolver={(img) => urlFor(img).width(1200).url()}
|
|
221
|
+
* />
|
|
222
|
+
* </Head>
|
|
223
|
+
* <main>...</main>
|
|
224
|
+
* </>
|
|
225
|
+
* )
|
|
226
|
+
* }
|
|
227
|
+
* ```
|
|
228
|
+
*
|
|
229
|
+
* @example Nuxt 3 / generic SSR (inside <Head> slot)
|
|
230
|
+
* ```tsx
|
|
231
|
+
* <Head>
|
|
232
|
+
* <SeoMetaTags data={seo} baseUrl="https://example.com" path="/" />
|
|
233
|
+
* </Head>
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
|
|
201
237
|
interface SeoMetaTagsProps {
|
|
202
238
|
/**
|
|
203
239
|
* The raw SEO object from Sanity.
|
|
@@ -239,6 +275,6 @@ interface SeoMetaTagsProps {
|
|
|
239
275
|
* - Twitter Card meta tags (`twitter:*`)
|
|
240
276
|
* - Any custom `seo.metaAttributes` as `<meta name="..." content="...">`
|
|
241
277
|
*/
|
|
242
|
-
declare function SeoMetaTags({ data, baseUrl, path, defaults, imageUrlResolver }: SeoMetaTagsProps):
|
|
278
|
+
declare function SeoMetaTags({ data, baseUrl, path, defaults, imageUrlResolver, }: SeoMetaTagsProps): React.JSX.Element;
|
|
243
279
|
|
|
244
280
|
export { type BuildSeoMetaOptions, type SeoFieldsInput, type SeoMetaDefaults, SeoMetaTags, type SeoMetaTagsProps, type SeoMetadata, buildSeoMeta, sanitizeOGType, sanitizeTwitterCard };
|
package/dist/next.js
CHANGED
|
@@ -27,24 +27,27 @@ function sanitizeTwitterCard(value) {
|
|
|
27
27
|
}
|
|
28
28
|
return "summary_large_image";
|
|
29
29
|
}
|
|
30
|
-
function
|
|
31
|
-
var _a, _b
|
|
32
|
-
const { seo, baseUrl = "", path = "", defaults = {}, imageUrlResolver } = options;
|
|
33
|
-
const normalizedBase = baseUrl.replace(/\/+$/, "");
|
|
34
|
-
const normalizedPath = path.replace(/^\/+/, "");
|
|
35
|
-
const fullUrl = [normalizedBase, normalizedPath].filter(Boolean).join("/");
|
|
36
|
-
let ogImageURL = defaults.ogImage || "";
|
|
30
|
+
function resolveOgImage(seo, defaults, imageUrlResolver) {
|
|
31
|
+
var _a, _b;
|
|
37
32
|
if (((_a = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _a.imageType) === "url" && seo.openGraph.imageUrl) {
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
33
|
+
return seo.openGraph.imageUrl;
|
|
34
|
+
}
|
|
35
|
+
if (((_b = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _b.image) && imageUrlResolver) {
|
|
36
|
+
return imageUrlResolver(seo.openGraph.image) || defaults.ogImage || "";
|
|
37
|
+
}
|
|
38
|
+
return defaults.ogImage || "";
|
|
39
|
+
}
|
|
40
|
+
function resolveTwitterImage(seo, ogImageURL, imageUrlResolver) {
|
|
41
|
+
var _a, _b;
|
|
42
|
+
if (((_a = seo == null ? void 0 : seo.twitter) == null ? void 0 : _a.imageType) === "url" && seo.twitter.imageUrl) {
|
|
43
|
+
return seo.twitter.imageUrl;
|
|
41
44
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
twitterImageURL = seo.twitter.imageUrl;
|
|
45
|
-
} else if (((_d = seo == null ? void 0 : seo.twitter) == null ? void 0 : _d.image) && imageUrlResolver) {
|
|
46
|
-
twitterImageURL = imageUrlResolver(seo.twitter.image) || twitterImageURL;
|
|
45
|
+
if (((_b = seo == null ? void 0 : seo.twitter) == null ? void 0 : _b.image) && imageUrlResolver) {
|
|
46
|
+
return imageUrlResolver(seo.twitter.image) || ogImageURL;
|
|
47
47
|
}
|
|
48
|
+
return ogImageURL;
|
|
49
|
+
}
|
|
50
|
+
function buildCustomMetaMap(seo) {
|
|
48
51
|
const other = {};
|
|
49
52
|
if (Array.isArray(seo == null ? void 0 : seo.metaAttributes)) {
|
|
50
53
|
for (const attr of seo.metaAttributes) {
|
|
@@ -53,33 +56,44 @@ function buildSeoMeta(options) {
|
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
}
|
|
56
|
-
|
|
59
|
+
return other;
|
|
60
|
+
}
|
|
61
|
+
function buildSeoMeta(options) {
|
|
62
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B;
|
|
63
|
+
const { seo, baseUrl = "", path = "", defaults = {}, imageUrlResolver } = options;
|
|
64
|
+
const normalizedBase = baseUrl.replace(/\/+$/, "");
|
|
65
|
+
const normalizedPath = path.replace(/^\/+/, "");
|
|
66
|
+
const fullUrl = [normalizedBase, normalizedPath].filter(Boolean).join("/");
|
|
67
|
+
const ogImageURL = resolveOgImage(seo, defaults, imageUrlResolver);
|
|
68
|
+
const twitterImageURL = resolveTwitterImage(seo, ogImageURL, imageUrlResolver);
|
|
69
|
+
const other = buildCustomMetaMap(seo);
|
|
70
|
+
const ogUrl = ((_a = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _a.url) || fullUrl;
|
|
57
71
|
return __spreadValues({
|
|
58
|
-
title: (
|
|
59
|
-
description: (
|
|
60
|
-
keywords: ((
|
|
72
|
+
title: (_c = (_b = seo == null ? void 0 : seo.title) != null ? _b : defaults.title) != null ? _c : null,
|
|
73
|
+
description: (_e = (_d = seo == null ? void 0 : seo.description) != null ? _d : defaults.description) != null ? _e : null,
|
|
74
|
+
keywords: ((_f = seo == null ? void 0 : seo.keywords) == null ? void 0 : _f.length) ? seo.keywords : void 0,
|
|
61
75
|
robots: {
|
|
62
|
-
index: !((
|
|
63
|
-
follow: !((
|
|
76
|
+
index: !((_g = seo == null ? void 0 : seo.robots) == null ? void 0 : _g.noIndex),
|
|
77
|
+
follow: !((_h = seo == null ? void 0 : seo.robots) == null ? void 0 : _h.noFollow),
|
|
64
78
|
googleBot: {
|
|
65
|
-
index: !((
|
|
66
|
-
follow: !((
|
|
79
|
+
index: !((_i = seo == null ? void 0 : seo.robots) == null ? void 0 : _i.noIndex),
|
|
80
|
+
follow: !((_j = seo == null ? void 0 : seo.robots) == null ? void 0 : _j.noFollow)
|
|
67
81
|
}
|
|
68
82
|
},
|
|
69
83
|
openGraph: {
|
|
70
|
-
type: sanitizeOGType((
|
|
84
|
+
type: sanitizeOGType((_l = (_k = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _k.type) != null ? _l : void 0),
|
|
71
85
|
url: ogUrl || void 0,
|
|
72
|
-
title: (
|
|
73
|
-
description: (
|
|
74
|
-
siteName: (
|
|
86
|
+
title: (_n = (_m = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _m.title) != null ? _n : defaults.title,
|
|
87
|
+
description: (_p = (_o = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _o.description) != null ? _p : defaults.description,
|
|
88
|
+
siteName: (_r = (_q = seo == null ? void 0 : seo.openGraph) == null ? void 0 : _q.siteName) != null ? _r : defaults.siteName,
|
|
75
89
|
images: ogImageURL ? [{ url: ogImageURL }] : []
|
|
76
90
|
},
|
|
77
91
|
twitter: {
|
|
78
|
-
card: sanitizeTwitterCard((
|
|
79
|
-
site: (
|
|
80
|
-
creator: (
|
|
81
|
-
title: (
|
|
82
|
-
description: (
|
|
92
|
+
card: sanitizeTwitterCard((_t = (_s = seo == null ? void 0 : seo.twitter) == null ? void 0 : _s.card) != null ? _t : void 0),
|
|
93
|
+
site: (_v = (_u = seo == null ? void 0 : seo.twitter) == null ? void 0 : _u.site) != null ? _v : defaults.twitterSite,
|
|
94
|
+
creator: (_x = (_w = seo == null ? void 0 : seo.twitter) == null ? void 0 : _w.creator) != null ? _x : defaults.twitterCreator,
|
|
95
|
+
title: (_z = (_y = seo == null ? void 0 : seo.twitter) == null ? void 0 : _y.title) != null ? _z : defaults.title,
|
|
96
|
+
description: (_B = (_A = seo == null ? void 0 : seo.twitter) == null ? void 0 : _A.description) != null ? _B : defaults.description,
|
|
83
97
|
images: twitterImageURL ? [twitterImageURL] : []
|
|
84
98
|
},
|
|
85
99
|
alternates: {
|
|
@@ -87,7 +101,13 @@ function buildSeoMeta(options) {
|
|
|
87
101
|
}
|
|
88
102
|
}, Object.keys(other).length > 0 ? { other } : {});
|
|
89
103
|
}
|
|
90
|
-
function SeoMetaTags({
|
|
104
|
+
function SeoMetaTags({
|
|
105
|
+
data,
|
|
106
|
+
baseUrl,
|
|
107
|
+
path,
|
|
108
|
+
defaults,
|
|
109
|
+
imageUrlResolver
|
|
110
|
+
}) {
|
|
91
111
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
92
112
|
const meta = buildSeoMeta({ seo: data, baseUrl, path, defaults, imageUrlResolver });
|
|
93
113
|
const robotsContent = [
|