sanity-plugin-seofields 1.6.1 → 1.6.3
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/README.md +15 -3
- package/dist/SeoHealthDashboard-BEZVLLFG.js +4 -0
- package/dist/{SeoHealthDashboard-PY5MKJCZ.js.map → SeoHealthDashboard-BEZVLLFG.js.map} +1 -1
- package/dist/SeoHealthDashboard-D3XU3CUB.cjs +10 -0
- package/dist/{SeoHealthDashboard-FZTP4GS7.cjs.map → SeoHealthDashboard-D3XU3CUB.cjs.map} +1 -1
- package/dist/{SeoHealthTool-Z3O6NEKF.cjs → SeoHealthTool-4VZMD4TR.cjs} +4 -4
- package/dist/{SeoHealthTool-Z3O6NEKF.cjs.map → SeoHealthTool-4VZMD4TR.cjs.map} +1 -1
- package/dist/{SeoHealthTool-SKY7FAKK.js → SeoHealthTool-BSTYAKQS.js} +3 -3
- package/dist/{SeoHealthTool-SKY7FAKK.js.map → SeoHealthTool-BSTYAKQS.js.map} +1 -1
- package/dist/{SeoPreview-LWSWTIF5.cjs → SeoPreview-PYYVZMY3.cjs} +3 -3
- package/dist/SeoPreview-PYYVZMY3.cjs.map +1 -0
- package/dist/{SeoPreview-BQBKMYSG.js → SeoPreview-XVAZYHCL.js} +3 -3
- package/dist/SeoPreview-XVAZYHCL.js.map +1 -0
- package/dist/{chunk-77U7CMJP.cjs → chunk-BHIZQLY7.cjs} +135 -16
- package/dist/chunk-BHIZQLY7.cjs.map +1 -0
- package/dist/{chunk-KFFDQX22.js → chunk-HQTYQMP5.js} +135 -16
- package/dist/chunk-HQTYQMP5.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -6
- package/dist/index.d.ts +8 -6
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +19 -4
- package/dist/SeoHealthDashboard-FZTP4GS7.cjs +0 -10
- package/dist/SeoHealthDashboard-PY5MKJCZ.js +0 -4
- package/dist/SeoPreview-BQBKMYSG.js.map +0 -1
- package/dist/SeoPreview-LWSWTIF5.cjs.map +0 -1
- package/dist/chunk-77U7CMJP.cjs.map +0 -1
- package/dist/chunk-KFFDQX22.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
#
|
|
1
|
+
# sanity-plugin-seofields
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/sanity-plugin-seofields)
|
|
4
4
|
[](https://www.npmjs.com/package/sanity-plugin-seofields)
|
|
5
5
|
[](./LICENSE)
|
|
6
6
|
[](https://github.com/hardik-143/sanity-plugin-seofields)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
**The only Sanity SEO plugin with a built-in audit dashboard.**
|
|
9
|
+
|
|
10
|
+
Manage meta tags, Open Graph, Twitter Cards, robots directives, and 38 Schema.org/JSON-LD types — all inside Sanity Studio v3/v4/v5.
|
|
9
11
|
|
|
10
12
|
📖 **[Full Documentation →](https://sanity-plugin-seofields.thehardik.in/docs)**
|
|
11
13
|
|
|
12
14
|
---
|
|
13
15
|
|
|
16
|
+
> ⭐ If this plugin saves you time, please [leave a rating on the Sanity Plugin Directory](https://www.sanity.io/plugins/sanity-plugin-seofields), [star it on GitHub](https://github.com/hardik-143/sanity-plugin-seofields), and [leave a review on the docs site](https://sanity-plugin-seofields.thehardik.in/reviews). It helps other developers find it.
|
|
17
|
+
|
|
18
|
+
<!-- Demo GIF: SEO Health Dashboard in action -->
|
|
19
|
+
<!-- Add a screen recording here showing the SEO Health Dashboard scoring documents, the live SERP preview, and the Schema.org JSON-LD editor -->
|
|
20
|
+
<!-- Recommended tools: LICEcap (Mac/Windows), Kap (Mac), or ScreenToGif (Windows) -->
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
14
24
|
## Installation
|
|
15
25
|
|
|
16
26
|
```bash
|
|
@@ -91,7 +101,9 @@ seofields({
|
|
|
91
101
|
|
|
92
102
|
## SEO Health Dashboard
|
|
93
103
|
|
|
94
|
-
|
|
104
|
+
> **This is the feature that sets this plugin apart from every other Sanity SEO plugin.**
|
|
105
|
+
|
|
106
|
+
A built-in Studio tool that audits SEO completeness across all your documents at once — scores each document, highlights missing fields, and links directly to what needs fixing. No external tools. No leaving Studio.
|
|
95
107
|
|
|
96
108
|
Requires a free license key — [get yours here](https://sanity-plugin-seofields.thehardik.in/get-license).
|
|
97
109
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"SeoHealthDashboard-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"SeoHealthDashboard-BEZVLLFG.js"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkBHIZQLY7_cjs = require('./chunk-BHIZQLY7.cjs');
|
|
4
|
+
require('./chunk-S367Y35J.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
module.exports = chunkBHIZQLY7_cjs.SeoHealthDashboard_default;
|
|
9
|
+
//# sourceMappingURL=SeoHealthDashboard-D3XU3CUB.cjs.map
|
|
10
|
+
//# sourceMappingURL=SeoHealthDashboard-D3XU3CUB.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"SeoHealthDashboard-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"SeoHealthDashboard-D3XU3CUB.cjs"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkBHIZQLY7_cjs = require('./chunk-BHIZQLY7.cjs');
|
|
4
4
|
var chunkS367Y35J_cjs = require('./chunk-S367Y35J.cjs');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
|
|
7
7
|
var SeoHealthTool = (props) => {
|
|
8
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8
|
+
return /* @__PURE__ */ jsxRuntime.jsx(chunkBHIZQLY7_cjs.SeoHealthDashboard_default, chunkS367Y35J_cjs.__spreadValues({}, props));
|
|
9
9
|
};
|
|
10
10
|
var SeoHealthTool_default = SeoHealthTool;
|
|
11
11
|
|
|
12
12
|
module.exports = SeoHealthTool_default;
|
|
13
|
-
//# sourceMappingURL=SeoHealthTool-
|
|
14
|
-
//# sourceMappingURL=SeoHealthTool-
|
|
13
|
+
//# sourceMappingURL=SeoHealthTool-4VZMD4TR.cjs.map
|
|
14
|
+
//# sourceMappingURL=SeoHealthTool-4VZMD4TR.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/SeoHealthTool.tsx"],"names":["jsx","SeoHealthDashboard_default"],"mappings":";;;;;;AAMA,IAAM,aAAA,GAAgB,CAAC,KAAA,KAAmC;AACxD,EAAA,uBAAOA,cAAA,CAACC,mFAAuB,KAAA,CAAO,CAAA;AACxC,CAAA;AAEA,IAAO,qBAAA,GAAQ","file":"SeoHealthTool-
|
|
1
|
+
{"version":3,"sources":["../src/components/SeoHealthTool.tsx"],"names":["jsx","SeoHealthDashboard_default"],"mappings":";;;;;;AAMA,IAAM,aAAA,GAAgB,CAAC,KAAA,KAAmC;AACxD,EAAA,uBAAOA,cAAA,CAACC,mFAAuB,KAAA,CAAO,CAAA;AACxC,CAAA;AAEA,IAAO,qBAAA,GAAQ","file":"SeoHealthTool-4VZMD4TR.cjs","sourcesContent":["import SeoHealthDashboard, {SeoHealthDashboardProps} from './SeoHealthDashboard'\n\n/**\n * Sanity Tool component for the SEO Health Dashboard\n * This component wraps the SeoHealthDashboard for use as a custom tool in Sanity Studio\n */\nconst SeoHealthTool = (props: SeoHealthDashboardProps) => {\n return <SeoHealthDashboard {...props} />\n}\n\nexport default SeoHealthTool\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SeoHealthDashboard_default } from './chunk-
|
|
1
|
+
import { SeoHealthDashboard_default } from './chunk-HQTYQMP5.js';
|
|
2
2
|
import { __spreadValues } from './chunk-2NMEKWO5.js';
|
|
3
3
|
import { jsx } from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -8,5 +8,5 @@ var SeoHealthTool = (props) => {
|
|
|
8
8
|
var SeoHealthTool_default = SeoHealthTool;
|
|
9
9
|
|
|
10
10
|
export { SeoHealthTool_default as default };
|
|
11
|
-
//# sourceMappingURL=SeoHealthTool-
|
|
12
|
-
//# sourceMappingURL=SeoHealthTool-
|
|
11
|
+
//# sourceMappingURL=SeoHealthTool-BSTYAKQS.js.map
|
|
12
|
+
//# sourceMappingURL=SeoHealthTool-BSTYAKQS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/SeoHealthTool.tsx"],"names":[],"mappings":";;;;AAMA,IAAM,aAAA,GAAgB,CAAC,KAAA,KAAmC;AACxD,EAAA,uBAAO,GAAA,CAAC,+CAAuB,KAAA,CAAO,CAAA;AACxC,CAAA;AAEA,IAAO,qBAAA,GAAQ","file":"SeoHealthTool-
|
|
1
|
+
{"version":3,"sources":["../src/components/SeoHealthTool.tsx"],"names":[],"mappings":";;;;AAMA,IAAM,aAAA,GAAgB,CAAC,KAAA,KAAmC;AACxD,EAAA,uBAAO,GAAA,CAAC,+CAAuB,KAAA,CAAO,CAAA;AACxC,CAAA;AAEA,IAAO,qBAAA,GAAQ","file":"SeoHealthTool-BSTYAKQS.js","sourcesContent":["import SeoHealthDashboard, {SeoHealthDashboardProps} from './SeoHealthDashboard'\n\n/**\n * Sanity Tool component for the SEO Health Dashboard\n * This component wraps the SeoHealthDashboard for use as a custom tool in Sanity Studio\n */\nconst SeoHealthTool = (props: SeoHealthDashboardProps) => {\n return <SeoHealthDashboard {...props} />\n}\n\nexport default SeoHealthTool\n"]}
|
|
@@ -166,7 +166,7 @@ var SeoPreview = (props) => {
|
|
|
166
166
|
/* @__PURE__ */ jsxRuntime.jsxs(PreviewBody, { children: [
|
|
167
167
|
/* @__PURE__ */ jsxRuntime.jsx(SerpUrl, { children: finalUrl ? urlDisplay : "example.com \u203A page-url" }),
|
|
168
168
|
/* @__PURE__ */ jsxRuntime.jsx(SerpTitle, { children: title && title.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
169
|
-
chunkIFDLKZET_cjs.truncate(title, Math.max(1, 60 - titleSuffix.length)),
|
|
169
|
+
chunkIFDLKZET_cjs.truncate(title, Math.max(1, 60 - (titleSuffix ? titleSuffix.length + 2 : 0))),
|
|
170
170
|
titleSuffix && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
171
171
|
"span",
|
|
172
172
|
{
|
|
@@ -185,5 +185,5 @@ var SeoPreview = (props) => {
|
|
|
185
185
|
var SeoPreview_default = SeoPreview;
|
|
186
186
|
|
|
187
187
|
module.exports = SeoPreview_default;
|
|
188
|
-
//# sourceMappingURL=SeoPreview-
|
|
189
|
-
//# sourceMappingURL=SeoPreview-
|
|
188
|
+
//# sourceMappingURL=SeoPreview-PYYVZMY3.cjs.map
|
|
189
|
+
//# sourceMappingURL=SeoPreview-PYYVZMY3.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/SeoPreview.tsx"],"names":["styled","useClient","useState","useEffect","useFormValue","jsx","Box","jsxs","Fragment","truncate"],"mappings":"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","file":"SeoPreview-PYYVZMY3.cjs","sourcesContent":["import {Box} from '@sanity/ui'\nimport {type ReactElement, useEffect, useState} from 'react'\nimport {StringInputProps, useClient, useFormValue} from 'sanity'\nimport styled from 'styled-components'\n\nimport {truncate} from '../utils/seoUtils'\n\nconst PreviewContainer = styled.div`\n max-width: 600px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #ffffff;\n border: 1px solid #dadce0;\n border-radius: 8px;\n overflow: hidden;\n`\n\nconst PreviewHeader = styled.div`\n background: #f8f9fa;\n padding: 12px 16px;\n border-bottom: 1px solid #dadce0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n`\n\nconst PreviewBody = styled.div`\n padding: 16px;\n`\n\nconst SerpUrl = styled.p`\n margin: 0 0 4px;\n color: #006621;\n font-size: 13px;\n line-height: 1.4;\n word-break: break-word;\n`\n\nconst SerpTitle = styled.h3`\n margin: 0 0 8px;\n color: #1a0dab;\n font-size: 18px;\n font-weight: 500;\n line-height: 1.4;\n word-break: break-word;\n\n &:hover {\n text-decoration: underline;\n }\n`\n\nconst SerpDescription = styled.p`\n margin: 0;\n color: #545454;\n font-size: 14px;\n line-height: 1.6;\n word-break: break-word;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n`\n\nconst LiveIndicator = styled.span`\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: #4f46e5;\n background: #f0f4ff;\n padding: 4px 8px;\n border-radius: 4px;\n`\n\nconst SeoPreview = (props: StringInputProps): ReactElement => {\n const {path, schemaType} = props\n const {options} = schemaType as {\n options?: {\n baseUrl?: string\n apiVersion?: string\n prefix?: ((doc: {_type?: string} & Record<string, unknown>) => string) | string\n titleSuffix?: ((doc: {_type?: string} & Record<string, unknown>) => string) | string\n titleSuffixInheritColor?: boolean\n titleSuffixQuery?: string\n }\n }\n const baseUrl = options?.baseUrl || 'https://www.example.com'\n const prefixFunction = options?.prefix as\n | ((doc: {_type?: string} & Record<string, unknown>) => string)\n | undefined\n const titleSuffixOption = options?.titleSuffix\n const titleSuffixInheritColor = options?.titleSuffixInheritColor ?? false\n const titleSuffixQuery = options?.titleSuffixQuery\n\n const client = useClient({apiVersion: options?.apiVersion ?? '2024-01-01'})\n const [groqTitleSuffix, setGroqTitleSuffix] = useState<string>('')\n\n useEffect(() => {\n if (!titleSuffixQuery) return\n client\n .fetch<string>(titleSuffixQuery)\n .then((result) => {\n setGroqTitleSuffix(result === null || result === undefined ? '' : String(result))\n })\n .catch(() => {\n setGroqTitleSuffix('')\n })\n }, [titleSuffixQuery, client])\n const parent = useFormValue([path[0]]) || {\n title: '',\n description: '',\n canonicalUrl: '',\n }\n const rootDoc: {\n slug?: {current: string}\n } = useFormValue([]) || {\n slug: {current: ''},\n }\n const slug: string = rootDoc?.slug?.current || ''\n\n const {\n title,\n description,\n canonicalUrl: url,\n } = parent as {\n title?: string\n description?: string\n canonicalUrl?: string\n }\n\n const getTitleSuffix = (): string => {\n if (titleSuffixQuery) return groqTitleSuffix\n if (!titleSuffixOption) return ''\n if (typeof titleSuffixOption === 'function') {\n return titleSuffixOption(rootDoc as {_type?: string} & Record<string, unknown>)\n }\n return titleSuffixOption\n }\n const titleSuffix: string = getTitleSuffix()\n\n // Build full URL\n const base = (url || baseUrl)?.replace(/\\/+$/, '')\n const slugStr = String(slug || '').replace(/^\\/+/, '')\n const pref = String(\n prefixFunction ? prefixFunction(rootDoc as {slug?: {current: string}}) : '',\n ).replace(/^\\/+|\\/+$/g, '')\n const urlPath = [pref, slugStr].filter(Boolean).join('/')\n const finalUrl = urlPath ? `${base}/${urlPath}` : base\n\n // Extract domain for display\n const domain = (() => {\n try {\n const u = new URL(finalUrl || base)\n return u.hostname\n } catch {\n return 'example.com'\n }\n })()\n\n // Format URL display with › separator\n const urlDisplay = `${domain}${urlPath ? ` › ${urlPath.split('/').slice(-1)[0]}` : ''}`\n\n return (\n <Box padding={3}>\n <PreviewContainer>\n <PreviewHeader>\n <span\n style={{\n fontSize: '11px',\n color: '#5f6368',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }}\n >\n Search Preview\n </span>\n <LiveIndicator>\n <span\n style={{\n width: '4px',\n height: '4px',\n borderRadius: '50%',\n backgroundColor: '#4f46e5',\n display: 'inline-block',\n }}\n />\n Live\n </LiveIndicator>\n </PreviewHeader>\n\n <PreviewBody>\n <SerpUrl>{finalUrl ? urlDisplay : 'example.com › page-url'}</SerpUrl>\n <SerpTitle>\n {title && title.length > 0 ? (\n <>\n {truncate(title, Math.max(1, 60 - (titleSuffix ? titleSuffix.length + 2 : 0)))}\n {titleSuffix && (\n <span\n style={\n titleSuffixInheritColor ? undefined : {color: '#70757a', fontWeight: 400}\n }\n >\n | {titleSuffix}\n </span>\n )}\n </>\n ) : (\n 'Your SEO Title will appear here'\n )}\n </SerpTitle>\n <SerpDescription>\n {description && description.length > 0\n ? truncate(description, 160)\n : 'Your meta description will show up here. Make it compelling!'}\n </SerpDescription>\n </PreviewBody>\n </PreviewContainer>\n </Box>\n )\n}\n\nexport default SeoPreview\n"]}
|
|
@@ -160,7 +160,7 @@ var SeoPreview = (props) => {
|
|
|
160
160
|
/* @__PURE__ */ jsxs(PreviewBody, { children: [
|
|
161
161
|
/* @__PURE__ */ jsx(SerpUrl, { children: finalUrl ? urlDisplay : "example.com \u203A page-url" }),
|
|
162
162
|
/* @__PURE__ */ jsx(SerpTitle, { children: title && title.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
163
|
-
truncate(title, Math.max(1, 60 - titleSuffix.length)),
|
|
163
|
+
truncate(title, Math.max(1, 60 - (titleSuffix ? titleSuffix.length + 2 : 0))),
|
|
164
164
|
titleSuffix && /* @__PURE__ */ jsxs(
|
|
165
165
|
"span",
|
|
166
166
|
{
|
|
@@ -179,5 +179,5 @@ var SeoPreview = (props) => {
|
|
|
179
179
|
var SeoPreview_default = SeoPreview;
|
|
180
180
|
|
|
181
181
|
export { SeoPreview_default as default };
|
|
182
|
-
//# sourceMappingURL=SeoPreview-
|
|
183
|
-
//# sourceMappingURL=SeoPreview-
|
|
182
|
+
//# sourceMappingURL=SeoPreview-XVAZYHCL.js.map
|
|
183
|
+
//# sourceMappingURL=SeoPreview-XVAZYHCL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/SeoPreview.tsx"],"names":[],"mappings":"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","file":"SeoPreview-XVAZYHCL.js","sourcesContent":["import {Box} from '@sanity/ui'\nimport {type ReactElement, useEffect, useState} from 'react'\nimport {StringInputProps, useClient, useFormValue} from 'sanity'\nimport styled from 'styled-components'\n\nimport {truncate} from '../utils/seoUtils'\n\nconst PreviewContainer = styled.div`\n max-width: 600px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #ffffff;\n border: 1px solid #dadce0;\n border-radius: 8px;\n overflow: hidden;\n`\n\nconst PreviewHeader = styled.div`\n background: #f8f9fa;\n padding: 12px 16px;\n border-bottom: 1px solid #dadce0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n`\n\nconst PreviewBody = styled.div`\n padding: 16px;\n`\n\nconst SerpUrl = styled.p`\n margin: 0 0 4px;\n color: #006621;\n font-size: 13px;\n line-height: 1.4;\n word-break: break-word;\n`\n\nconst SerpTitle = styled.h3`\n margin: 0 0 8px;\n color: #1a0dab;\n font-size: 18px;\n font-weight: 500;\n line-height: 1.4;\n word-break: break-word;\n\n &:hover {\n text-decoration: underline;\n }\n`\n\nconst SerpDescription = styled.p`\n margin: 0;\n color: #545454;\n font-size: 14px;\n line-height: 1.6;\n word-break: break-word;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n`\n\nconst LiveIndicator = styled.span`\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: #4f46e5;\n background: #f0f4ff;\n padding: 4px 8px;\n border-radius: 4px;\n`\n\nconst SeoPreview = (props: StringInputProps): ReactElement => {\n const {path, schemaType} = props\n const {options} = schemaType as {\n options?: {\n baseUrl?: string\n apiVersion?: string\n prefix?: ((doc: {_type?: string} & Record<string, unknown>) => string) | string\n titleSuffix?: ((doc: {_type?: string} & Record<string, unknown>) => string) | string\n titleSuffixInheritColor?: boolean\n titleSuffixQuery?: string\n }\n }\n const baseUrl = options?.baseUrl || 'https://www.example.com'\n const prefixFunction = options?.prefix as\n | ((doc: {_type?: string} & Record<string, unknown>) => string)\n | undefined\n const titleSuffixOption = options?.titleSuffix\n const titleSuffixInheritColor = options?.titleSuffixInheritColor ?? false\n const titleSuffixQuery = options?.titleSuffixQuery\n\n const client = useClient({apiVersion: options?.apiVersion ?? '2024-01-01'})\n const [groqTitleSuffix, setGroqTitleSuffix] = useState<string>('')\n\n useEffect(() => {\n if (!titleSuffixQuery) return\n client\n .fetch<string>(titleSuffixQuery)\n .then((result) => {\n setGroqTitleSuffix(result === null || result === undefined ? '' : String(result))\n })\n .catch(() => {\n setGroqTitleSuffix('')\n })\n }, [titleSuffixQuery, client])\n const parent = useFormValue([path[0]]) || {\n title: '',\n description: '',\n canonicalUrl: '',\n }\n const rootDoc: {\n slug?: {current: string}\n } = useFormValue([]) || {\n slug: {current: ''},\n }\n const slug: string = rootDoc?.slug?.current || ''\n\n const {\n title,\n description,\n canonicalUrl: url,\n } = parent as {\n title?: string\n description?: string\n canonicalUrl?: string\n }\n\n const getTitleSuffix = (): string => {\n if (titleSuffixQuery) return groqTitleSuffix\n if (!titleSuffixOption) return ''\n if (typeof titleSuffixOption === 'function') {\n return titleSuffixOption(rootDoc as {_type?: string} & Record<string, unknown>)\n }\n return titleSuffixOption\n }\n const titleSuffix: string = getTitleSuffix()\n\n // Build full URL\n const base = (url || baseUrl)?.replace(/\\/+$/, '')\n const slugStr = String(slug || '').replace(/^\\/+/, '')\n const pref = String(\n prefixFunction ? prefixFunction(rootDoc as {slug?: {current: string}}) : '',\n ).replace(/^\\/+|\\/+$/g, '')\n const urlPath = [pref, slugStr].filter(Boolean).join('/')\n const finalUrl = urlPath ? `${base}/${urlPath}` : base\n\n // Extract domain for display\n const domain = (() => {\n try {\n const u = new URL(finalUrl || base)\n return u.hostname\n } catch {\n return 'example.com'\n }\n })()\n\n // Format URL display with › separator\n const urlDisplay = `${domain}${urlPath ? ` › ${urlPath.split('/').slice(-1)[0]}` : ''}`\n\n return (\n <Box padding={3}>\n <PreviewContainer>\n <PreviewHeader>\n <span\n style={{\n fontSize: '11px',\n color: '#5f6368',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }}\n >\n Search Preview\n </span>\n <LiveIndicator>\n <span\n style={{\n width: '4px',\n height: '4px',\n borderRadius: '50%',\n backgroundColor: '#4f46e5',\n display: 'inline-block',\n }}\n />\n Live\n </LiveIndicator>\n </PreviewHeader>\n\n <PreviewBody>\n <SerpUrl>{finalUrl ? urlDisplay : 'example.com › page-url'}</SerpUrl>\n <SerpTitle>\n {title && title.length > 0 ? (\n <>\n {truncate(title, Math.max(1, 60 - (titleSuffix ? titleSuffix.length + 2 : 0)))}\n {titleSuffix && (\n <span\n style={\n titleSuffixInheritColor ? undefined : {color: '#70757a', fontWeight: 400}\n }\n >\n | {titleSuffix}\n </span>\n )}\n </>\n ) : (\n 'Your SEO Title will appear here'\n )}\n </SerpTitle>\n <SerpDescription>\n {description && description.length > 0\n ? truncate(description, 160)\n : 'Your meta description will show up here. Make it compelling!'}\n </SerpDescription>\n </PreviewBody>\n </PreviewContainer>\n </Box>\n )\n}\n\nexport default SeoPreview\n"]}
|
|
@@ -1046,6 +1046,81 @@ var RenderLicenseInvalid = ({ licenseKey, validateLicense }) => /* @__PURE__ */
|
|
|
1046
1046
|
}
|
|
1047
1047
|
)
|
|
1048
1048
|
] }) }) });
|
|
1049
|
+
var LegacyBannerWrap = styled__default.default.div`
|
|
1050
|
+
display: flex;
|
|
1051
|
+
align-items: flex-start;
|
|
1052
|
+
gap: 12px;
|
|
1053
|
+
padding: 14px 20px;
|
|
1054
|
+
margin-bottom: 20px;
|
|
1055
|
+
background: #fffbeb;
|
|
1056
|
+
border-bottom: 1px solid #fde68a;
|
|
1057
|
+
color: #92400e;
|
|
1058
|
+
font-size: 13px;
|
|
1059
|
+
line-height: 1.5;
|
|
1060
|
+
`;
|
|
1061
|
+
var LegacyBannerLink = styled__default.default.a`
|
|
1062
|
+
display: inline-block;
|
|
1063
|
+
padding: 5px 14px;
|
|
1064
|
+
background: #f59e0b;
|
|
1065
|
+
color: #fff;
|
|
1066
|
+
border-radius: 6px;
|
|
1067
|
+
font-size: 12px;
|
|
1068
|
+
font-weight: 600;
|
|
1069
|
+
text-decoration: none;
|
|
1070
|
+
&:hover {
|
|
1071
|
+
background: #d97706;
|
|
1072
|
+
}
|
|
1073
|
+
`;
|
|
1074
|
+
var ButtonWrapper = styled__default.default.div`
|
|
1075
|
+
display: flex;
|
|
1076
|
+
gap: 12px;
|
|
1077
|
+
flex-wrap: wrap;
|
|
1078
|
+
align-items: center;
|
|
1079
|
+
margin-top: 6px;
|
|
1080
|
+
`;
|
|
1081
|
+
var VerifyButton = styled__default.default.button`
|
|
1082
|
+
display: inline-block;
|
|
1083
|
+
padding: 5px 14px;
|
|
1084
|
+
background: #10b981;
|
|
1085
|
+
color: #fff;
|
|
1086
|
+
border-radius: 6px;
|
|
1087
|
+
font-size: 12px;
|
|
1088
|
+
font-weight: 600;
|
|
1089
|
+
border: none;
|
|
1090
|
+
cursor: pointer;
|
|
1091
|
+
text-decoration: none;
|
|
1092
|
+
&:hover {
|
|
1093
|
+
background: #059669;
|
|
1094
|
+
}
|
|
1095
|
+
`;
|
|
1096
|
+
var RenderLegacyBanner = ({ upgradeUrl, cutoffDate, onVerifyUpgrade }) => {
|
|
1097
|
+
const deadline = cutoffDate ? new Date(cutoffDate).toLocaleDateString("en-US", {
|
|
1098
|
+
month: "long",
|
|
1099
|
+
day: "numeric",
|
|
1100
|
+
year: "numeric"
|
|
1101
|
+
}) : null;
|
|
1102
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(LegacyBannerWrap, { children: [
|
|
1103
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "18px", lineHeight: 1 }, children: "\u26A0\uFE0F" }),
|
|
1104
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1105
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Legacy free access \u2014 upgrade required" }),
|
|
1106
|
+
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
1107
|
+
deadline ? `Your free beta access expires on ${deadline}. After that date, a paid license is required.` : "Your free beta access will be transitioning to paid. Upgrade now to keep access.",
|
|
1108
|
+
/* @__PURE__ */ jsxRuntime.jsx("br", {}),
|
|
1109
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ButtonWrapper, { children: [
|
|
1110
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1111
|
+
LegacyBannerLink,
|
|
1112
|
+
{
|
|
1113
|
+
href: upgradeUrl != null ? upgradeUrl : "https://sanity-plugin-seofields.thehardik.in/get-license",
|
|
1114
|
+
target: "_blank",
|
|
1115
|
+
rel: "noopener noreferrer",
|
|
1116
|
+
children: "Upgrade for $10/project \u2192"
|
|
1117
|
+
}
|
|
1118
|
+
),
|
|
1119
|
+
onVerifyUpgrade && /* @__PURE__ */ jsxRuntime.jsx(VerifyButton, { onClick: onVerifyUpgrade, children: "Already paid? Click here to verify your license \u2192" })
|
|
1120
|
+
] })
|
|
1121
|
+
] })
|
|
1122
|
+
] });
|
|
1123
|
+
};
|
|
1049
1124
|
var scoreMetaTitle = (title) => {
|
|
1050
1125
|
const issues = [];
|
|
1051
1126
|
let score = 0;
|
|
@@ -1330,7 +1405,10 @@ var SeoHealthDashboard = ({
|
|
|
1330
1405
|
return Array.from(groups.values());
|
|
1331
1406
|
}, [allDeprecationWarnings]);
|
|
1332
1407
|
const client = sanity.useClient({ apiVersion });
|
|
1333
|
-
const [licenseStatus, setLicenseStatus] = react.useState(
|
|
1408
|
+
const [licenseStatus, setLicenseStatus] = react.useState(
|
|
1409
|
+
"loading"
|
|
1410
|
+
);
|
|
1411
|
+
const [legacyInfo, setLegacyInfo] = react.useState({});
|
|
1334
1412
|
const [documents, setDocuments] = react.useState([]);
|
|
1335
1413
|
const [loading, setLoading] = react.useState(true);
|
|
1336
1414
|
const [isRefreshing, setIsRefreshing] = react.useState(false);
|
|
@@ -1419,6 +1497,28 @@ var SeoHealthDashboard = ({
|
|
|
1419
1497
|
}
|
|
1420
1498
|
setCurrentPage(1);
|
|
1421
1499
|
}, []);
|
|
1500
|
+
const applyLicenseState = react.useCallback(
|
|
1501
|
+
({ valid, legacy = false, upgradeUrl, cutoffDate }) => {
|
|
1502
|
+
if (valid && legacy) {
|
|
1503
|
+
setLegacyInfo({ upgradeUrl, cutoffDate });
|
|
1504
|
+
setLicenseStatus("legacy");
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
setLegacyInfo({});
|
|
1508
|
+
setLicenseStatus(valid ? "valid" : "invalid");
|
|
1509
|
+
},
|
|
1510
|
+
[]
|
|
1511
|
+
);
|
|
1512
|
+
const readCachedLicenseState = react.useCallback((cacheKey) => {
|
|
1513
|
+
try {
|
|
1514
|
+
const cached = sessionStorage.getItem(cacheKey);
|
|
1515
|
+
if (!cached) return null;
|
|
1516
|
+
const parsed = JSON.parse(cached);
|
|
1517
|
+
return Date.now() - parsed.ts < CACHE_TTL_MS ? parsed : null;
|
|
1518
|
+
} catch (e) {
|
|
1519
|
+
return null;
|
|
1520
|
+
}
|
|
1521
|
+
}, []);
|
|
1422
1522
|
const validateLicense = react.useCallback(
|
|
1423
1523
|
async (forceRefresh = false) => {
|
|
1424
1524
|
var _a;
|
|
@@ -1439,16 +1539,10 @@ var SeoHealthDashboard = ({
|
|
|
1439
1539
|
}
|
|
1440
1540
|
}
|
|
1441
1541
|
if (!forceRefresh) {
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
if (Date.now() - ts < CACHE_TTL_MS) {
|
|
1447
|
-
setLicenseStatus(valid ? "valid" : "invalid");
|
|
1448
|
-
return;
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1451
|
-
} catch (e) {
|
|
1542
|
+
const cachedLicenseState = readCachedLicenseState(cacheKey);
|
|
1543
|
+
if (cachedLicenseState) {
|
|
1544
|
+
applyLicenseState(cachedLicenseState);
|
|
1545
|
+
return;
|
|
1452
1546
|
}
|
|
1453
1547
|
}
|
|
1454
1548
|
setLicenseStatus("loading");
|
|
@@ -1458,10 +1552,21 @@ var SeoHealthDashboard = ({
|
|
|
1458
1552
|
headers: { "Content-Type": "application/json" },
|
|
1459
1553
|
body: JSON.stringify({ licenseKey, projectId })
|
|
1460
1554
|
});
|
|
1555
|
+
const data = await res.json().catch(() => ({}));
|
|
1461
1556
|
const valid = res.ok;
|
|
1462
|
-
|
|
1557
|
+
const legacy = valid && data.legacy === true;
|
|
1558
|
+
applyLicenseState({ valid, legacy, upgradeUrl: data.upgradeUrl, cutoffDate: data.cutoffDate });
|
|
1463
1559
|
try {
|
|
1464
|
-
sessionStorage.setItem(
|
|
1560
|
+
sessionStorage.setItem(
|
|
1561
|
+
cacheKey,
|
|
1562
|
+
JSON.stringify({
|
|
1563
|
+
valid,
|
|
1564
|
+
legacy,
|
|
1565
|
+
upgradeUrl: data.upgradeUrl,
|
|
1566
|
+
cutoffDate: data.cutoffDate,
|
|
1567
|
+
ts: Date.now()
|
|
1568
|
+
})
|
|
1569
|
+
);
|
|
1465
1570
|
} catch (e) {
|
|
1466
1571
|
}
|
|
1467
1572
|
} catch (e) {
|
|
@@ -1469,8 +1574,11 @@ var SeoHealthDashboard = ({
|
|
|
1469
1574
|
}
|
|
1470
1575
|
},
|
|
1471
1576
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1472
|
-
[licenseKey, previewMode]
|
|
1577
|
+
[applyLicenseState, licenseKey, previewMode, readCachedLicenseState]
|
|
1473
1578
|
);
|
|
1579
|
+
const handleVerifyUpgrade = react.useCallback(() => {
|
|
1580
|
+
validateLicense(true);
|
|
1581
|
+
}, [validateLicense]);
|
|
1474
1582
|
react.useEffect(() => {
|
|
1475
1583
|
validateLicense();
|
|
1476
1584
|
}, [licenseKey, previewMode]);
|
|
@@ -2041,11 +2149,22 @@ var SeoHealthDashboard = ({
|
|
|
2041
2149
|
return /* @__PURE__ */ jsxRuntime.jsxs(DashboardContainer, { style: currentVars, children: [
|
|
2042
2150
|
licenseStatus === "loading" && /* @__PURE__ */ jsxRuntime.jsx(RenderLicenseLoading, { text: loadingLicense }),
|
|
2043
2151
|
licenseStatus === "invalid" && /* @__PURE__ */ jsxRuntime.jsx(RenderLicenseInvalid, { licenseKey, validateLicense }),
|
|
2152
|
+
licenseStatus === "legacy" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2153
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2154
|
+
RenderLegacyBanner,
|
|
2155
|
+
{
|
|
2156
|
+
upgradeUrl: legacyInfo.upgradeUrl,
|
|
2157
|
+
cutoffDate: legacyInfo.cutoffDate,
|
|
2158
|
+
onVerifyUpgrade: handleVerifyUpgrade
|
|
2159
|
+
}
|
|
2160
|
+
),
|
|
2161
|
+
renderDashboardContent()
|
|
2162
|
+
] }),
|
|
2044
2163
|
licenseStatus === "valid" && renderDashboardContent()
|
|
2045
2164
|
] });
|
|
2046
2165
|
};
|
|
2047
2166
|
var SeoHealthDashboard_default = SeoHealthDashboard;
|
|
2048
2167
|
|
|
2049
2168
|
exports.SeoHealthDashboard_default = SeoHealthDashboard_default;
|
|
2050
|
-
//# sourceMappingURL=chunk-
|
|
2051
|
-
//# sourceMappingURL=chunk-
|
|
2169
|
+
//# sourceMappingURL=chunk-BHIZQLY7.cjs.map
|
|
2170
|
+
//# sourceMappingURL=chunk-BHIZQLY7.cjs.map
|