sanity-plugin-seofields 1.2.4 → 1.2.6

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 (49) hide show
  1. package/dist/index.cjs +2604 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.d.cts +422 -0
  4. package/dist/index.d.ts +339 -492
  5. package/dist/index.js +1284 -2013
  6. package/dist/index.js.map +1 -1
  7. package/dist/next.cjs +182 -0
  8. package/dist/next.cjs.map +1 -0
  9. package/dist/next.d.cts +241 -0
  10. package/dist/next.d.ts +202 -295
  11. package/dist/next.js +110 -70
  12. package/dist/next.js.map +1 -1
  13. package/dist/types-B91ena4g.d.cts +89 -0
  14. package/dist/types-B91ena4g.d.ts +89 -0
  15. package/package.json +37 -18
  16. package/dist/index.d.mts +0 -575
  17. package/dist/index.mjs +0 -3292
  18. package/dist/index.mjs.map +0 -1
  19. package/dist/next.d.mts +0 -334
  20. package/dist/next.mjs +0 -102
  21. package/dist/next.mjs.map +0 -1
  22. package/sanity.json +0 -8
  23. package/src/components/SeoHealthDashboard.tsx +0 -1568
  24. package/src/components/SeoHealthPane.tsx +0 -81
  25. package/src/components/SeoHealthTool.tsx +0 -11
  26. package/src/components/SeoPreview.tsx +0 -178
  27. package/src/components/meta/MetaDescription.tsx +0 -39
  28. package/src/components/meta/MetaTitle.tsx +0 -44
  29. package/src/components/openGraph/OgDescription.tsx +0 -46
  30. package/src/components/openGraph/OgTitle.tsx +0 -45
  31. package/src/components/twitter/twitterDescription.tsx +0 -45
  32. package/src/components/twitter/twitterTitle.tsx +0 -45
  33. package/src/helpers/SeoMetaTags.tsx +0 -154
  34. package/src/helpers/seoMeta.ts +0 -283
  35. package/src/index.ts +0 -26
  36. package/src/next.ts +0 -12
  37. package/src/plugin.ts +0 -344
  38. package/src/schemas/index.ts +0 -121
  39. package/src/schemas/types/index.ts +0 -20
  40. package/src/schemas/types/metaAttribute/index.ts +0 -60
  41. package/src/schemas/types/metaTag/index.ts +0 -17
  42. package/src/schemas/types/openGraph/index.ts +0 -114
  43. package/src/schemas/types/robots/index.ts +0 -26
  44. package/src/schemas/types/twitter/index.ts +0 -108
  45. package/src/types.ts +0 -108
  46. package/src/utils/fieldsUtils.ts +0 -160
  47. package/src/utils/seoUtils.ts +0 -423
  48. package/src/utils/utils.ts +0 -9
  49. package/v2-incompatible.js +0 -11
package/dist/index.d.mts DELETED
@@ -1,575 +0,0 @@
1
- import type {ComponentBuilder} from 'sanity/structure'
2
- import {JSX} from 'react'
3
- import {ObjectDefinition} from 'sanity'
4
- import {Plugin as Plugin_2} from 'sanity'
5
- import {PreviewConfig} from 'sanity'
6
- import {default as React_2} from 'react'
7
- import {SchemaTypeDefinition} from 'sanity'
8
- import type {StructureBuilder} from 'sanity/structure'
9
-
10
- export declare type AllFieldKeys = SeoFieldKeys | openGraphFieldKeys | twitterFieldKeys
11
-
12
- export declare function allSchemas(config?: SeoFieldsPluginConfig): SchemaTypeDefinition[]
13
-
14
- /**
15
- * Creates a desk-structure pane for the SEO Health Dashboard.
16
- *
17
- * Returns a **`ComponentBuilder`** with a built-in `.child()` resolver so that
18
- * clicking any document row opens the document editor as a split pane to the right.
19
- *
20
- * Use it **directly** as the `.child()` value — do **not** wrap it in `S.component()`.
21
- *
22
- * ```ts
23
- * // sanity.config.ts
24
- * structure: (S) =>
25
- * S.list().items([
26
- * S.listItem()
27
- * .title('SEO Health')
28
- * .child(
29
- * createSeoHealthPane(S, {
30
- * licenseKey: 'SEOF-XXXX-XXXX-XXXX',
31
- * query: `*[_type == "post" && defined(seo)]{ _id, _type, title, slug, seo, _updatedAt }`,
32
- * })
33
- * ),
34
- * ])
35
- * ```
36
- */
37
- export declare function createSeoHealthPane(
38
- optionsOrS: StructureBuilder,
39
- optionsWhenS: SeoHealthPaneOptions,
40
- ): ComponentBuilder
41
-
42
- export declare interface DocumentWithSeoHealth {
43
- _id: string
44
- _type: string
45
- title?: string
46
- slug?: {
47
- current: string
48
- }
49
- seo?: SeoFields
50
- _updatedAt?: string
51
- health: SeoHealthMetrics
52
- }
53
-
54
- export declare interface FieldVisibilityConfig {
55
- hiddenFields?: ValidHiddenFieldKeys[]
56
- }
57
-
58
- declare interface MetaAttribute {
59
- _type: 'metaAttribute'
60
- key?: string
61
- type?: 'string' | 'image'
62
- value?: string
63
- image?: SanityImage
64
- }
65
-
66
- export declare const metaAttributeSchema: {
67
- type: 'object'
68
- name: 'metaAttribute'
69
- } & Omit<ObjectDefinition, 'preview'> & {
70
- preview?:
71
- | PreviewConfig<
72
- {
73
- attributeName: string
74
- attributeValueString: string
75
- attributeValueImage: string
76
- },
77
- Record<'attributeName' | 'attributeValueString' | 'attributeValueImage', any>
78
- >
79
- | undefined
80
- }
81
-
82
- export declare const metaTagSchema: {
83
- type: 'object'
84
- name: 'metaTag'
85
- } & Omit<ObjectDefinition, 'preview'> & {
86
- preview?: PreviewConfig<Record<string, string>, Record<never, any>> | undefined
87
- }
88
-
89
- export declare type openGraphFieldKeys =
90
- | 'openGraphUrl'
91
- | 'openGraphTitle'
92
- | 'openGraphDescription'
93
- | 'openGraphSiteName'
94
- | 'openGraphType'
95
- | 'openGraphImageType'
96
- | 'openGraphImage'
97
- | 'openGraphImageUrl'
98
-
99
- export declare function openGraphSchema(config?: SeoFieldsPluginConfig): SchemaTypeDefinition
100
-
101
- declare interface OpenGraphSettings {
102
- _type: 'openGraph'
103
- /** The canonical URL for OpenGraph (og:url). Maps to the `url` field in Sanity. */
104
- url?: string
105
- title?: string
106
- description?: string
107
- siteName?: string
108
- type?: 'website' | 'article' | 'profile' | 'book' | 'music' | 'video' | 'product'
109
- imageType?: 'upload' | 'url'
110
- image?: SanityImageWithAlt
111
- imageUrl?: string
112
- }
113
-
114
- export declare const robotsSchema: {
115
- type: 'object'
116
- name: 'robots'
117
- } & Omit<ObjectDefinition, 'preview'> & {
118
- preview?: PreviewConfig<Record<string, string>, Record<never, any>> | undefined
119
- }
120
-
121
- declare interface RobotsSettings {
122
- noIndex?: boolean
123
- noFollow?: boolean
124
- }
125
-
126
- declare interface SanityImage {
127
- _type: 'image'
128
- asset: {
129
- _ref: string
130
- _type: 'reference'
131
- }
132
- hotspot?: {
133
- x: number
134
- y: number
135
- height: number
136
- width: number
137
- }
138
- crop?: {
139
- top: number
140
- bottom: number
141
- left: number
142
- right: number
143
- }
144
- alt?: string
145
- }
146
-
147
- declare interface SanityImageWithAlt extends SanityImage {
148
- alt: string
149
- }
150
-
151
- export declare interface SeoFieldConfig {
152
- title?: string
153
- description?: string
154
- }
155
-
156
- export declare type SeoFieldKeys =
157
- | 'title'
158
- | 'description'
159
- | 'canonicalUrl'
160
- | 'metaImage'
161
- | 'keywords'
162
- | 'metaAttributes'
163
- | 'robots'
164
-
165
- declare interface SeoFields {
166
- _type: 'seoFields'
167
- robots?: RobotsSettings
168
- preview?: string
169
- title?: string
170
- description?: string
171
- metaImage?: SanityImage
172
- metaAttributes?: MetaAttribute[]
173
- keywords?: string[]
174
- canonicalUrl?: string
175
- openGraph?: OpenGraphSettings
176
- twitter?: TwitterCardSettings
177
- }
178
-
179
- declare const seofields: Plugin_2<void | SeoFieldsPluginConfig>
180
- export default seofields
181
-
182
- export declare interface SeoFieldsPluginConfig {
183
- /**
184
- * Enable or configure the SEO preview feature.
185
- * If set to `true`, the SEO preview will be enabled with default settings.
186
- * If set to an object, you can provide a custom prefix function to modify the URL prefix in the preview.
187
- * The prefix function receives the current document as an argument and should return a string.
188
- * Example:
189
- * ```
190
- * seoPreview: {
191
- * prefix: (doc) => `/${doc.slug?.current || 'untitled'}`
192
- * }
193
- * ```
194
- */
195
- seoPreview?:
196
- | boolean
197
- | {
198
- prefix?: (
199
- doc: {
200
- _type?: string
201
- } & Record<string, unknown>,
202
- ) => string
203
- }
204
- /**
205
- * A mapping of field keys to their configuration settings.
206
- * This allows customization of field titles and descriptions.
207
- * For example, to change the title of the 'title' field:
208
- */
209
- fieldOverrides?: Partial<Record<AllFieldKeys, SeoFieldConfig>>
210
- /**
211
- * A mapping of document types to field visibility configurations.
212
- * This allows you to specify which fields should be hidden for specific document types.
213
- */
214
- fieldVisibility?: Record<string, FieldVisibilityConfig>
215
- /**
216
- * A list of fields that should be hidden by default in all document types.
217
- * This can be overridden by specific document type settings in `fieldVisibility`.
218
- */
219
- defaultHiddenFields?: ValidHiddenFieldKeys[]
220
- /**
221
- * The base URL of your website, used for generating full URLs in the SEO preview.
222
- * Defaults to 'https://www.example.com' if not provided.
223
- */
224
- baseUrl?: string
225
- /**
226
- * Enable or configure the SEO Health Dashboard tool.
227
- * If set to `true`, the dashboard is enabled with all defaults.
228
- * If set to an object, you can customise the tool and dashboard settings.
229
- * Defaults to `true`.
230
- * Example:
231
- * ```
232
- * healthDashboard: {
233
- * toolTitle: 'SEO Overview', // Studio nav tab label
234
- * content: {
235
- * icon: '🔍', // Emoji icon shown before the page heading
236
- * title: 'My SEO Dashboard',// Page heading inside the tool (no emoji)
237
- * description: 'Track SEO across all documents', // Subtitle under the heading
238
- * },
239
- * display: {
240
- * typeColumn: false, // Hide the document type column (default: true)
241
- * documentId: false, // Hide the document ID under titles (default: true)
242
- * },
243
- * query: {
244
- * // Option 1 – filter by specific document types
245
- * types: ['post', 'page'],
246
- * // Option 2 – provide a full custom GROQ query (takes precedence over `types`)
247
- * // Must return documents with at least: _id, _type, title, seo, _updatedAt
248
- * groq: `*[seo != null && defined(slug.current)]{ _id, _type, title, slug, seo, _updatedAt }`,
249
- * },
250
- * }
251
- * ```
252
- */
253
- healthDashboard?:
254
- | boolean
255
- | {
256
- tool?: {
257
- title?: string
258
- name?: string
259
- }
260
- toolTitle?: string
261
- content?: {
262
- icon?: string
263
- title?: string
264
- description?: string
265
- /** Text shown while the license key is being verified. Defaults to "Verifying license…" */
266
- loadingLicense?: string
267
- /** Text shown while documents are being fetched. Defaults to "Loading documents…" */
268
- loadingDocuments?: string
269
- /** Text shown when the query returns zero results. Defaults to "No documents found" */
270
- noDocuments?: string
271
- }
272
- display?: {
273
- typeColumn?: boolean
274
- documentId?: boolean
275
- }
276
- query?: {
277
- /**
278
- * Limit the dashboard to specific document types.
279
- * Example: `['post', 'page']`
280
- */
281
- types?: string[]
282
- /**
283
- * When using `types`, also require the `seo` field to be non-null.
284
- * Set to `false` to include documents of those types even if `seo` is missing.
285
- * Defaults to `true`.
286
- */
287
- requireSeo?: boolean
288
- /**
289
- * Provide a fully custom GROQ query. Takes precedence over `types`.
290
- * The query must return documents with at least: _id, _type, title, seo, _updatedAt
291
- */
292
- groq?: string
293
- }
294
- /**
295
- * The Sanity API version to use for the client (e.g. '2023-01-01').
296
- * Defaults to '2023-01-01'.
297
- */
298
- apiVersion?: string
299
- /**
300
- * License key for the SEO Health Dashboard pro feature.
301
- * Obtain a license at https://sanity-plugin-seofields.thehardik.in
302
- */
303
- licenseKey?: string
304
- /**
305
- * Map raw `_type` values to human-readable display labels.
306
- * Used in both the Type column and the Type filter dropdown.
307
- * Any type without an entry falls back to the raw `_type` string.
308
- *
309
- * @example
310
- * typeLabels: { productDrug: 'Products', singleCondition: 'Condition' }
311
- */
312
- typeLabels?: Record<string, string>
313
- /**
314
- * Controls how the document type is rendered in the Type column.
315
- * - `'badge'` (default) — coloured pill
316
- * - `'text'` — plain text, useful for dense layouts
317
- */
318
- typeColumnMode?: 'badge' | 'text'
319
- /**
320
- * The document field to use as the display title in the dashboard.
321
- *
322
- * - `string` — use this field for every document type (e.g. `'name'`)
323
- * - `Record<string, string>` — per-type mapping; unmapped types fall back to `title`
324
- *
325
- * @example
326
- * titleField: 'name'
327
- *
328
- * @example
329
- * titleField: { post: 'title', product: 'name', category: 'label' }
330
- */
331
- titleField?: string | Record<string, string>
332
- /**
333
- * Callback function to render a custom badge next to the document title.
334
- * Receives the full document and should return badge data or undefined.
335
- *
336
- * @example
337
- * docBadge: (doc) => {
338
- * if (doc.services === 'NHS')
339
- * return { label: 'NHS', bgColor: '#e0f2fe', textColor: '#0369a1' }
340
- * if (doc.services === 'Private')
341
- * return { label: 'Private', bgColor: '#fef3c7', textColor: '#92400e' }
342
- * }
343
- */
344
- docBadge?: (doc: DocumentWithSeoHealth & Record<string, unknown>) =>
345
- | {
346
- label: string
347
- bgColor?: string
348
- textColor?: string
349
- fontSize?: string
350
- }
351
- | undefined
352
- /**
353
- * The `name` of the Sanity structure tool that contains the monitored documents.
354
- * Required when you have multiple structure tools and the documents live in a
355
- * non-default one. Clicking a title will navigate to
356
- * `/{basePath}/{structureTool}/intent/edit/…` directly.
357
- *
358
- * @example
359
- * structureTool: 'common'
360
- */
361
- structureTool?: string
362
- /**
363
- * Enable preview/demo mode to show dummy data.
364
- * Useful for testing, documentation, or showcasing the dashboard.
365
- * When enabled, displays realistic sample documents with various SEO scores.
366
- * Defaults to `false`.
367
- *
368
- * @example
369
- * previewMode: true
370
- */
371
- previewMode?: boolean
372
- }
373
- }
374
-
375
- export declare function seoFieldsSchema(config?: SeoFieldsPluginConfig): SchemaTypeDefinition
376
-
377
- export declare const SeoHealthDashboard: React_2.FC<SeoHealthDashboardProps>
378
-
379
- declare interface SeoHealthDashboardProps {
380
- icon?: string
381
- title?: string
382
- description?: string
383
- showTypeColumn?: boolean
384
- showDocumentId?: boolean
385
- /**
386
- * Limit the dashboard to specific document type names.
387
- * If both queryTypes and customQuery are provided, customQuery takes precedence.
388
- */
389
- queryTypes?: string[]
390
- /**
391
- * When using `queryTypes`, also filter by `seo != null`.
392
- * Set to `false` to include documents of those types even without an seo field.
393
- * Defaults to `true`.
394
- */
395
- queryRequireSeo?: boolean
396
- /**
397
- * A fully custom GROQ query used to fetch documents.
398
- * Must return objects with at least: _id, _type, title, seo, _updatedAt
399
- * Takes precedence over queryTypes.
400
- */
401
- customQuery?: string
402
- /**
403
- * The Sanity API version to use for the client (e.g. '2023-01-01').
404
- * Defaults to '2023-01-01'.
405
- */
406
- apiVersion?: string
407
- /**
408
- * License key for the SEO Health Dashboard.
409
- * Obtain a key at https://sanity-plugin-seofields.thehardik.in
410
- */
411
- licenseKey?: string
412
- /**
413
- * Map raw `_type` values to human-readable display labels used in the
414
- * Type column and the Type filter dropdown.
415
- * Any type without an entry falls back to the raw `_type` string.
416
- *
417
- * @example
418
- * typeLabels={{ productDrug: 'Products', singleCondition: 'Condition' }}
419
- */
420
- typeLabels?: Record<string, string>
421
- /**
422
- * Controls how the type is rendered in the Type column.
423
- * - `'badge'` (default) — coloured pill, consistent with score badges
424
- * - `'text'` — plain text, useful for dense layouts
425
- */
426
- typeColumnMode?: 'badge' | 'text'
427
- /**
428
- * The document field to use as the display title.
429
- *
430
- * - `string` — use this field for every document type (e.g. `'name'`)
431
- * - `Record<string, string>` — per-type mapping; unmapped types fall back to `title`
432
- *
433
- * @example
434
- * // Same field for all types
435
- * titleField: 'name'
436
- *
437
- * @example
438
- * // Different field per type
439
- * titleField: { post: 'title', product: 'name', category: 'label' }
440
- */
441
- titleField?: string | Record<string, string>
442
- /**
443
- * Callback function to render a custom badge next to the document title.
444
- * Receives the full document and should return badge data or undefined.
445
- *
446
- * @example
447
- * docBadge: (doc) => {
448
- * if (doc.services === 'NHS')
449
- * return { label: 'NHS', bgColor: '#e0f2fe', textColor: '#0369a1' }
450
- * if (doc.services === 'Private')
451
- * return { label: 'Private', bgColor: '#fef3c7', textColor: '#92400e' }
452
- * }
453
- */
454
- docBadge?: (doc: DocumentWithSeoHealth & Record<string, unknown>) =>
455
- | {
456
- label: string
457
- bgColor?: string
458
- textColor?: string
459
- fontSize?: string
460
- }
461
- | undefined
462
- /**
463
- * Custom text shown while the license key is being verified.
464
- * Defaults to `"Verifying license…"`.
465
- */
466
- loadingLicense?: React_2.ReactNode
467
- /**
468
- * Custom text shown while documents are being fetched.
469
- * Defaults to `"Loading documents…"`.
470
- */
471
- loadingDocuments?: React_2.ReactNode
472
- /**
473
- * Custom text shown when the query returns zero results.
474
- * Defaults to `"No documents found"`.
475
- */
476
- noDocuments?: React_2.ReactNode
477
- /**
478
- * Enable preview/demo mode to show dummy data.
479
- * Useful for testing, documentation, or showcasing the dashboard.
480
- * When enabled, displays realistic sample documents with various SEO scores.
481
- * Defaults to `false`.
482
- */
483
- previewMode?: boolean
484
- /**
485
- * When `true`, clicking a document title opens the document editor as a split
486
- * pane to the right, keeping the SEO Health pane visible on the left.
487
- * This uses Sanity's pane router and requires the component to be rendered
488
- * inside a desk-structure pane context (i.e. via `createSeoHealthPane`).
489
- *
490
- * When `false` (default), clicking navigates to the document via the standard
491
- * intent-link system (full navigation).
492
- *
493
- * This is set to `true` automatically by `createSeoHealthPane`.
494
- */
495
- openInPane?: boolean
496
- /**
497
- * The `name` of the Sanity structure tool that contains the monitored documents.
498
- * When provided, clicking a document title navigates directly to that tool's
499
- * intent URL (`/{basePath}/{structureTool}/intent/edit/id=…;type=…/`) instead of
500
- * using the generic intent resolver, which always picks the first registered tool.
501
- *
502
- * Required when you have multiple structure tools and the documents live in a
503
- * non-default one (e.g. `name: 'common'`).
504
- *
505
- * @example
506
- * structureTool: 'common'
507
- */
508
- structureTool?: string
509
- }
510
-
511
- export declare interface SeoHealthMetrics {
512
- score: number
513
- status: SeoHealthStatus
514
- issues: string[]
515
- }
516
-
517
- /**
518
- * Options accepted by `createSeoHealthPane`.
519
- * All props from `SeoHealthDashboardProps` are supported.
520
- *
521
- * `licenseKey` is **required** — the dashboard will not render without it.
522
- */
523
- export declare interface SeoHealthPaneOptions extends Omit<SeoHealthDashboardProps, 'customQuery'> {
524
- /** Required license key (format: `SEOF-XXXX-XXXX-XXXX`). */
525
- licenseKey: string
526
- /**
527
- * A fully custom GROQ query used to fetch documents for the dashboard.
528
- * The query must return documents with at least: `_id`, `_type`, `title`, `seo`, `_updatedAt`.
529
- *
530
- * Takes precedence over `queryTypes` when both are provided.
531
- *
532
- * @example
533
- * query: `*[_type in ["post","page"] && defined(seo)]{ _id, _type, title, slug, seo, _updatedAt }`
534
- */
535
- query?: string
536
- }
537
-
538
- export declare type SeoHealthStatus = 'excellent' | 'good' | 'fair' | 'poor' | 'missing'
539
-
540
- /**
541
- * Sanity Tool component for the SEO Health Dashboard
542
- * This component wraps the SeoHealthDashboard for use as a custom tool in Sanity Studio
543
- */
544
- export declare const SeoHealthTool: (props: SeoHealthDashboardProps) => JSX.Element
545
-
546
- declare interface TwitterCardSettings {
547
- _type: 'twitter'
548
- card?: 'summary' | 'summary_large_image' | 'app' | 'player'
549
- site?: string
550
- creator?: string
551
- title?: string
552
- description?: string
553
- imageType?: 'upload' | 'url'
554
- image?: SanityImageWithAlt
555
- imageUrl?: string
556
- }
557
-
558
- export declare type twitterFieldKeys =
559
- | 'twitterCard'
560
- | 'twitterSite'
561
- | 'twitterCreator'
562
- | 'twitterTitle'
563
- | 'twitterDescription'
564
- | 'twitterImageType'
565
- | 'twitterImage'
566
- | 'twitterImageUrl'
567
-
568
- export declare function twitterSchema(config?: SeoFieldsPluginConfig): SchemaTypeDefinition
569
-
570
- export declare type ValidHiddenFieldKeys = Exclude<
571
- AllFieldKeys,
572
- 'openGraphImageUrl' | 'twitterImageUrl' | 'openGraphImageType' | 'twitterImageType'
573
- >
574
-
575
- export {}