sanity-plugin-seofields 1.6.5 → 1.8.0
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 +355 -79
- package/dist/SchemaOrgJsonLdPreview-DJLkIPq4.d.cts +78 -0
- package/dist/SchemaOrgJsonLdPreview-DJLkIPq4.d.ts +78 -0
- package/dist/SeoHealthDashboard-AEKVVMUR-7NWV3C3Y.js +4 -0
- package/dist/SeoHealthDashboard-AEKVVMUR-7NWV3C3Y.js.map +1 -0
- package/dist/SeoHealthDashboard-AEKVVMUR-XWKJUH24.cjs +10 -0
- package/dist/SeoHealthDashboard-AEKVVMUR-XWKJUH24.cjs.map +1 -0
- package/dist/SeoHealthTool-2KKQJLJL.cjs +11 -0
- package/dist/{SeoHealthDashboard-BEZVLLFG.js.map → SeoHealthTool-2KKQJLJL.cjs.map} +1 -1
- package/dist/SeoHealthTool-3CUKGADZ.js +5 -0
- package/dist/{SeoHealthDashboard-D3XU3CUB.cjs.map → SeoHealthTool-3CUKGADZ.js.map} +1 -1
- package/dist/{SeoPreview-WYH7NYNM.cjs → SeoPreview-3EXR6FD4.cjs} +3 -3
- package/dist/{SeoPreview-WYH7NYNM.cjs.map → SeoPreview-3EXR6FD4.cjs.map} +1 -1
- package/dist/{SeoPreview-KEGGQSPJ.js → SeoPreview-4PPAF4NO.js} +3 -3
- package/dist/{SeoPreview-KEGGQSPJ.js.map → SeoPreview-4PPAF4NO.js.map} +1 -1
- package/dist/{chunk-S367Y35J.cjs → chunk-254YHUN3.cjs} +2 -15
- package/dist/{chunk-S367Y35J.cjs.map → chunk-254YHUN3.cjs.map} +1 -1
- package/dist/{chunk-HQTYQMP5.js → chunk-27XSYENH.js} +80 -29
- package/dist/chunk-27XSYENH.js.map +1 -0
- package/dist/{chunk-YHXUWGNA.cjs → chunk-B5IVI5LP.cjs} +918 -157
- package/dist/chunk-B5IVI5LP.cjs.map +1 -0
- package/dist/chunk-BNXMFD3T.cjs +431 -0
- package/dist/chunk-BNXMFD3T.cjs.map +1 -0
- package/dist/{chunk-2NMEKWO5.js → chunk-DDAAVRWG.js} +3 -15
- package/dist/{chunk-2NMEKWO5.js.map → chunk-DDAAVRWG.js.map} +1 -1
- package/dist/chunk-P6IOWIO2.cjs +480 -0
- package/dist/chunk-P6IOWIO2.cjs.map +1 -0
- package/dist/{chunk-XXA6WCWS.js → chunk-UOCZFYYP.js} +18 -203
- package/dist/chunk-UOCZFYYP.js.map +1 -0
- package/dist/{chunk-KTL6NYNG.js → chunk-VR44E62I.js} +897 -148
- package/dist/chunk-VR44E62I.js.map +1 -0
- package/dist/chunk-WKXHX3GO.js +424 -0
- package/dist/chunk-WKXHX3GO.js.map +1 -0
- package/dist/{chunk-BHIZQLY7.cjs → chunk-XZDLJ2N6.cjs} +84 -30
- package/dist/chunk-XZDLJ2N6.cjs.map +1 -0
- package/dist/cli.js +18 -18
- package/dist/{component-H52blyfc.d.ts → component-BzI-LHPw.d.cts} +9 -27
- package/dist/{component-CIE6Sy4F.d.cts → component-DEXwtemT.d.ts} +9 -27
- package/dist/define-cli.cjs +1 -1
- package/dist/define-cli.js +1 -1
- package/dist/index.cjs +1050 -94
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -202
- package/dist/index.d.ts +75 -202
- package/dist/index.js +1009 -63
- package/dist/index.js.map +1 -1
- package/dist/next.cjs +138 -116
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +9 -3
- package/dist/next.d.ts +9 -3
- package/dist/next.js +38 -32
- package/dist/next.js.map +1 -1
- package/dist/schema/next.cjs +105 -89
- package/dist/schema/next.d.cts +4 -4
- package/dist/schema/next.d.ts +4 -4
- package/dist/schema/next.js +4 -4
- package/dist/schema.cjs +219 -157
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +30 -16
- package/dist/schema.d.ts +30 -16
- package/dist/schema.js +41 -8
- package/dist/schema.js.map +1 -1
- package/dist/{types-Dp9Pfnt9.d.ts → types-BXSCbl6p.d.cts} +47 -2
- package/dist/{types-CyRdIF-3.d.cts → types-B_vjMPtM.d.cts} +1 -1
- package/dist/{types-BxcJinOf.d.cts → types-C19cQx5D.d.ts} +47 -2
- package/dist/{types-CbYb4MsN.d.ts → types-CW8qFdAn.d.ts} +1 -1
- package/dist/{types-BtSRRG6C.d.cts → types-yVmQfby9.d.cts} +8 -16
- package/dist/{types-BtSRRG6C.d.ts → types-yVmQfby9.d.ts} +8 -16
- package/package.json +2 -1
- package/dist/SeoHealthDashboard-BEZVLLFG.js +0 -4
- package/dist/SeoHealthDashboard-D3XU3CUB.cjs +0 -10
- package/dist/SeoHealthTool-4VZMD4TR.cjs +0 -14
- package/dist/SeoHealthTool-4VZMD4TR.cjs.map +0 -1
- package/dist/SeoHealthTool-BSTYAKQS.js +0 -12
- package/dist/SeoHealthTool-BSTYAKQS.js.map +0 -1
- package/dist/chunk-BCTPOWXA.cjs +0 -669
- package/dist/chunk-BCTPOWXA.cjs.map +0 -1
- package/dist/chunk-BHIZQLY7.cjs.map +0 -1
- package/dist/chunk-HQTYQMP5.js.map +0 -1
- package/dist/chunk-KTL6NYNG.js.map +0 -1
- package/dist/chunk-XXA6WCWS.js.map +0 -1
- package/dist/chunk-YHXUWGNA.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -2,13 +2,469 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
var chunkB5IVI5LP_cjs = require('./chunk-B5IVI5LP.cjs');
|
|
5
6
|
var chunkZBHLMQTS_cjs = require('./chunk-ZBHLMQTS.cjs');
|
|
6
|
-
var
|
|
7
|
+
var chunkBNXMFD3T_cjs = require('./chunk-BNXMFD3T.cjs');
|
|
8
|
+
require('./chunk-XZDLJ2N6.cjs');
|
|
9
|
+
var chunk254YHUN3_cjs = require('./chunk-254YHUN3.cjs');
|
|
7
10
|
var react = require('react');
|
|
8
11
|
var sanity = require('sanity');
|
|
9
|
-
var ui = require('@sanity/ui');
|
|
10
12
|
var jsxRuntime = require('react/jsx-runtime');
|
|
13
|
+
var ui = require('@sanity/ui');
|
|
11
14
|
|
|
15
|
+
var GEOChecklist = (props) => {
|
|
16
|
+
var _a;
|
|
17
|
+
const { path, schemaType } = props;
|
|
18
|
+
const [expanded, setExpanded] = react.useState(false);
|
|
19
|
+
const licenseKey = (_a = schemaType.options) == null ? void 0 : _a.licenseKey;
|
|
20
|
+
const seoFields = sanity.useFormValue([path[0]]);
|
|
21
|
+
const rootDoc = sanity.useFormValue([]);
|
|
22
|
+
const freeChecks = react.useMemo(() => {
|
|
23
|
+
var _a2, _b, _c, _d;
|
|
24
|
+
const desc = (seoFields == null ? void 0 : seoFields.description) || "";
|
|
25
|
+
const title = (seoFields == null ? void 0 : seoFields.title) || "";
|
|
26
|
+
return [
|
|
27
|
+
{
|
|
28
|
+
id: "description_answer_ready",
|
|
29
|
+
label: "Description is answer-ready (100\u2013160 chars)",
|
|
30
|
+
pass: !!desc && desc.length >= 100 && desc.length <= 160,
|
|
31
|
+
hint: "Write a concise 100\u2013160 char answer that directly addresses user intent."
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "not_noindexed",
|
|
35
|
+
label: "Page is indexable (not noindex)",
|
|
36
|
+
pass: !((_a2 = seoFields == null ? void 0 : seoFields.robots) == null ? void 0 : _a2.noIndex),
|
|
37
|
+
hint: "Page is set to noindex \u2014 AI overviews cannot cite noindexed pages."
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "title_concise",
|
|
41
|
+
label: "Title is 30\u201360 characters",
|
|
42
|
+
pass: !!(title && title.length >= 30 && title.length <= 60),
|
|
43
|
+
hint: "Keep your title between 30\u201360 characters for optimal SERP and AI snippet display."
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: "og_image_present",
|
|
47
|
+
label: "OG or meta image present",
|
|
48
|
+
pass: !!(((_b = seoFields == null ? void 0 : seoFields.metaImage) == null ? void 0 : _b.asset) || ((_d = (_c = seoFields == null ? void 0 : seoFields.openGraph) == null ? void 0 : _c.image) == null ? void 0 : _d.asset)),
|
|
49
|
+
hint: "Add a meta or OG image for rich results and social previews."
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "has_keywords",
|
|
53
|
+
label: "Keywords added",
|
|
54
|
+
pass: !!((seoFields == null ? void 0 : seoFields.keywords) && seoFields.keywords.filter((k) => k && k.trim().length > 0).length > 0),
|
|
55
|
+
hint: "Add at least one keyword to improve topical signal for AI classifiers."
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
}, [seoFields]);
|
|
59
|
+
const proChecks = react.useMemo(
|
|
60
|
+
() => licenseKey ? chunkBNXMFD3T_cjs.buildGEOProChecks(seoFields, rootDoc) : null,
|
|
61
|
+
[licenseKey, seoFields, rootDoc]
|
|
62
|
+
);
|
|
63
|
+
const freePassing = freeChecks.filter((c) => c.pass).length;
|
|
64
|
+
const proPassing = proChecks ? proChecks.filter((c) => c.pass).length : 0;
|
|
65
|
+
const totalPassing = freePassing + (proChecks ? proPassing : 0);
|
|
66
|
+
const totalChecks = freeChecks.length + (proChecks ? proChecks.length : 0);
|
|
67
|
+
const percentage = totalChecks > 0 ? totalPassing / totalChecks * 100 : 0;
|
|
68
|
+
let scoreColor = "#dc2626";
|
|
69
|
+
let scoreBg = "#fef2f2";
|
|
70
|
+
let scoreText = "#b91c1c";
|
|
71
|
+
if (percentage >= 80) {
|
|
72
|
+
scoreColor = "#16a34a";
|
|
73
|
+
scoreBg = "#f0fdf4";
|
|
74
|
+
scoreText = "#15803d";
|
|
75
|
+
} else if (percentage >= 50) {
|
|
76
|
+
scoreColor = "#ca8a04";
|
|
77
|
+
scoreBg = "#fefce8";
|
|
78
|
+
scoreText = "#a16207";
|
|
79
|
+
}
|
|
80
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
81
|
+
"div",
|
|
82
|
+
{
|
|
83
|
+
style: {
|
|
84
|
+
borderRadius: 10,
|
|
85
|
+
border: "1px solid #e5e7eb",
|
|
86
|
+
overflow: "hidden",
|
|
87
|
+
fontFamily: "inherit"
|
|
88
|
+
},
|
|
89
|
+
children: [
|
|
90
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
91
|
+
"div",
|
|
92
|
+
{
|
|
93
|
+
style: {
|
|
94
|
+
padding: "16px 20px 14px",
|
|
95
|
+
borderBottom: "1px solid #f3f4f6",
|
|
96
|
+
display: "flex",
|
|
97
|
+
alignItems: "center",
|
|
98
|
+
justifyContent: "space-between",
|
|
99
|
+
gap: 12
|
|
100
|
+
},
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
103
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, fontWeight: 600, color: "#111827", marginBottom: 2 }, children: "AI Overview Readiness" }),
|
|
104
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: "#9ca3af" }, children: "Signals that improve visibility in AI-generated overviews" })
|
|
105
|
+
] }),
|
|
106
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
107
|
+
"div",
|
|
108
|
+
{
|
|
109
|
+
style: {
|
|
110
|
+
backgroundColor: scoreBg,
|
|
111
|
+
borderRadius: 20,
|
|
112
|
+
padding: "4px 12px",
|
|
113
|
+
display: "flex",
|
|
114
|
+
alignItems: "center",
|
|
115
|
+
gap: 4,
|
|
116
|
+
flexShrink: 0
|
|
117
|
+
},
|
|
118
|
+
children: [
|
|
119
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 16, fontWeight: 700, color: scoreColor }, children: totalPassing }),
|
|
120
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 12, color: scoreText, opacity: 0.7 }, children: [
|
|
121
|
+
"/ ",
|
|
122
|
+
totalChecks
|
|
123
|
+
] })
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
),
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: 3, backgroundColor: "#f3f4f6" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
131
|
+
"div",
|
|
132
|
+
{
|
|
133
|
+
style: {
|
|
134
|
+
height: "100%",
|
|
135
|
+
width: `${percentage}%`,
|
|
136
|
+
backgroundColor: scoreColor,
|
|
137
|
+
transition: "width 0.4s ease"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
) }),
|
|
141
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "10px 20px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
142
|
+
"button",
|
|
143
|
+
{
|
|
144
|
+
type: "button",
|
|
145
|
+
onClick: () => setExpanded((prev) => !prev),
|
|
146
|
+
style: {
|
|
147
|
+
background: "none",
|
|
148
|
+
border: "none",
|
|
149
|
+
padding: 0,
|
|
150
|
+
cursor: "pointer",
|
|
151
|
+
fontSize: 12,
|
|
152
|
+
color: "#6366f1",
|
|
153
|
+
fontWeight: 500,
|
|
154
|
+
display: "flex",
|
|
155
|
+
alignItems: "center",
|
|
156
|
+
gap: 4
|
|
157
|
+
},
|
|
158
|
+
children: [
|
|
159
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
160
|
+
"svg",
|
|
161
|
+
{
|
|
162
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
163
|
+
width: "12",
|
|
164
|
+
height: "12",
|
|
165
|
+
viewBox: "0 0 24 24",
|
|
166
|
+
fill: "none",
|
|
167
|
+
stroke: "currentColor",
|
|
168
|
+
strokeWidth: "2",
|
|
169
|
+
strokeLinecap: "round",
|
|
170
|
+
strokeLinejoin: "round",
|
|
171
|
+
style: {
|
|
172
|
+
display: "inline-block",
|
|
173
|
+
transform: expanded ? "rotate(90deg)" : "rotate(0deg)",
|
|
174
|
+
transition: "transform 0.2s ease",
|
|
175
|
+
flexShrink: 0
|
|
176
|
+
},
|
|
177
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" })
|
|
178
|
+
}
|
|
179
|
+
),
|
|
180
|
+
expanded ? "Hide checks" : "Show all checks"
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
) }),
|
|
184
|
+
expanded && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
185
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "0 20px 16px" }, children: [
|
|
186
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
187
|
+
"div",
|
|
188
|
+
{
|
|
189
|
+
style: {
|
|
190
|
+
fontSize: 10,
|
|
191
|
+
fontWeight: 700,
|
|
192
|
+
letterSpacing: "0.08em",
|
|
193
|
+
color: "#9ca3af",
|
|
194
|
+
marginBottom: 10,
|
|
195
|
+
textTransform: "uppercase"
|
|
196
|
+
},
|
|
197
|
+
children: "Core Checks"
|
|
198
|
+
}
|
|
199
|
+
),
|
|
200
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: freeChecks.map((check) => /* @__PURE__ */ jsxRuntime.jsx(CheckRow, { check }, check.id)) })
|
|
201
|
+
] }),
|
|
202
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
203
|
+
"div",
|
|
204
|
+
{
|
|
205
|
+
style: {
|
|
206
|
+
margin: "0 12px 12px",
|
|
207
|
+
borderRadius: 8,
|
|
208
|
+
backgroundColor: licenseKey ? "#faf5ff" : "#f9fafb",
|
|
209
|
+
border: `1px solid ${licenseKey ? "#e9d5ff" : "#f3f4f6"}`,
|
|
210
|
+
overflow: "hidden"
|
|
211
|
+
},
|
|
212
|
+
children: [
|
|
213
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
214
|
+
"div",
|
|
215
|
+
{
|
|
216
|
+
style: {
|
|
217
|
+
padding: "10px 16px",
|
|
218
|
+
borderBottom: `1px solid ${licenseKey ? "#e9d5ff" : "#f3f4f6"}`,
|
|
219
|
+
display: "flex",
|
|
220
|
+
alignItems: "center",
|
|
221
|
+
gap: 8
|
|
222
|
+
},
|
|
223
|
+
children: [
|
|
224
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
225
|
+
"span",
|
|
226
|
+
{
|
|
227
|
+
style: {
|
|
228
|
+
fontSize: 10,
|
|
229
|
+
fontWeight: 700,
|
|
230
|
+
letterSpacing: "0.08em",
|
|
231
|
+
color: licenseKey ? "#7c3aed" : "#9ca3af",
|
|
232
|
+
textTransform: "uppercase"
|
|
233
|
+
},
|
|
234
|
+
children: "Pro Insights"
|
|
235
|
+
}
|
|
236
|
+
),
|
|
237
|
+
!licenseKey && /* @__PURE__ */ jsxRuntime.jsx(
|
|
238
|
+
"span",
|
|
239
|
+
{
|
|
240
|
+
style: {
|
|
241
|
+
fontSize: 10,
|
|
242
|
+
backgroundColor: "#f3e8ff",
|
|
243
|
+
color: "#7c3aed",
|
|
244
|
+
borderRadius: 4,
|
|
245
|
+
padding: "1px 6px",
|
|
246
|
+
fontWeight: 600
|
|
247
|
+
},
|
|
248
|
+
children: "Unlock with licenseKey"
|
|
249
|
+
}
|
|
250
|
+
),
|
|
251
|
+
licenseKey && proChecks && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
252
|
+
"span",
|
|
253
|
+
{
|
|
254
|
+
style: {
|
|
255
|
+
fontSize: 10,
|
|
256
|
+
backgroundColor: "#d8b4fe",
|
|
257
|
+
color: "#5b21b6",
|
|
258
|
+
borderRadius: 4,
|
|
259
|
+
padding: "1px 6px",
|
|
260
|
+
fontWeight: 600
|
|
261
|
+
},
|
|
262
|
+
children: [
|
|
263
|
+
proPassing,
|
|
264
|
+
" / ",
|
|
265
|
+
proChecks.length,
|
|
266
|
+
" passing"
|
|
267
|
+
]
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
),
|
|
273
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "10px 16px" }, children: proChecks ? /* @__PURE__ */ jsxRuntime.jsx(chunkBNXMFD3T_cjs.GEOChecklistProChecks, { checks: proChecks }) : /* @__PURE__ */ jsxRuntime.jsx(chunkBNXMFD3T_cjs.GEOLockedTeaser, {}) })
|
|
274
|
+
]
|
|
275
|
+
}
|
|
276
|
+
)
|
|
277
|
+
] })
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
);
|
|
281
|
+
};
|
|
282
|
+
function CheckRow({ check }) {
|
|
283
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
284
|
+
"div",
|
|
285
|
+
{
|
|
286
|
+
style: {
|
|
287
|
+
display: "flex",
|
|
288
|
+
alignItems: "flex-start",
|
|
289
|
+
gap: 10,
|
|
290
|
+
padding: "9px 12px",
|
|
291
|
+
borderRadius: 7,
|
|
292
|
+
backgroundColor: check.pass ? "transparent" : "#fff8f8",
|
|
293
|
+
border: `1px solid ${check.pass ? "transparent" : "#fee2e2"}`
|
|
294
|
+
},
|
|
295
|
+
children: [
|
|
296
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
297
|
+
"div",
|
|
298
|
+
{
|
|
299
|
+
style: {
|
|
300
|
+
width: 20,
|
|
301
|
+
height: 20,
|
|
302
|
+
borderRadius: "50%",
|
|
303
|
+
backgroundColor: check.pass ? "#dcfce7" : "#fee2e2",
|
|
304
|
+
display: "flex",
|
|
305
|
+
alignItems: "center",
|
|
306
|
+
justifyContent: "center",
|
|
307
|
+
flexShrink: 0,
|
|
308
|
+
marginTop: 1
|
|
309
|
+
},
|
|
310
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
311
|
+
"span",
|
|
312
|
+
{
|
|
313
|
+
style: {
|
|
314
|
+
fontSize: 10,
|
|
315
|
+
fontWeight: 800,
|
|
316
|
+
color: check.pass ? "#16a34a" : "#dc2626",
|
|
317
|
+
lineHeight: 1
|
|
318
|
+
},
|
|
319
|
+
children: check.pass ? "\u2713" : "\u2717"
|
|
320
|
+
}
|
|
321
|
+
)
|
|
322
|
+
}
|
|
323
|
+
),
|
|
324
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
325
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
326
|
+
"div",
|
|
327
|
+
{
|
|
328
|
+
style: {
|
|
329
|
+
fontSize: 12,
|
|
330
|
+
fontWeight: 500,
|
|
331
|
+
color: check.pass ? "#374151" : "#1f2937",
|
|
332
|
+
lineHeight: 1.4
|
|
333
|
+
},
|
|
334
|
+
children: check.label
|
|
335
|
+
}
|
|
336
|
+
),
|
|
337
|
+
!check.pass && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: "#9ca3af", marginTop: 3, lineHeight: 1.5 }, children: check.hint })
|
|
338
|
+
] })
|
|
339
|
+
]
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
var GEOChecklist_default = GEOChecklist;
|
|
344
|
+
var FocusKeywordInput = (props) => {
|
|
345
|
+
var _a;
|
|
346
|
+
const { value, renderDefault, path } = props;
|
|
347
|
+
const parent = sanity.useFormValue([path[0]]);
|
|
348
|
+
const rootDoc = sanity.useFormValue([]);
|
|
349
|
+
const feedbackItems = react.useMemo(() => {
|
|
350
|
+
var _a2, _b;
|
|
351
|
+
if (!value) return [];
|
|
352
|
+
const kw = value.toLowerCase();
|
|
353
|
+
const title = ((parent == null ? void 0 : parent.title) || "").toLowerCase();
|
|
354
|
+
const description = ((parent == null ? void 0 : parent.description) || "").toLowerCase();
|
|
355
|
+
const slug = ((_a2 = rootDoc == null ? void 0 : rootDoc.slug) == null ? void 0 : _a2.current) || "";
|
|
356
|
+
const items = [];
|
|
357
|
+
if (title) {
|
|
358
|
+
if (title.startsWith(kw)) {
|
|
359
|
+
items.push({ text: "Keyword at start of title \u2014 excellent", color: "green" });
|
|
360
|
+
} else if (title.includes(kw)) {
|
|
361
|
+
items.push({
|
|
362
|
+
text: "Keyword in title \u2014 move it to the start for more prominence",
|
|
363
|
+
color: "orange"
|
|
364
|
+
});
|
|
365
|
+
} else {
|
|
366
|
+
items.push({ text: "Keyword missing from meta title", color: "red" });
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
if (description) {
|
|
370
|
+
if (description.includes(kw)) {
|
|
371
|
+
items.push({ text: "Keyword in meta description", color: "green" });
|
|
372
|
+
} else {
|
|
373
|
+
items.push({ text: "Not in description \u2014 include it naturally", color: "orange" });
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (slug) {
|
|
377
|
+
const kwSlug = kw.replace(/\s+/g, "-");
|
|
378
|
+
if (slug.includes(kwSlug)) {
|
|
379
|
+
items.push({ text: "Keyword in URL slug", color: "green" });
|
|
380
|
+
} else {
|
|
381
|
+
items.push({
|
|
382
|
+
text: "Keyword not in URL slug \u2014 consider it for new pages",
|
|
383
|
+
color: "orange"
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
const safeKw = kw.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
388
|
+
if (((_b = title.match(new RegExp(safeKw, "g"))) != null ? _b : []).length > 2) {
|
|
389
|
+
items.push({
|
|
390
|
+
text: "Keyword appears too many times in title \u2014 avoid stuffing",
|
|
391
|
+
color: "red"
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
return items;
|
|
395
|
+
}, [value, parent == null ? void 0 : parent.title, parent == null ? void 0 : parent.description, (_a = rootDoc == null ? void 0 : rootDoc.slug) == null ? void 0 : _a.current]);
|
|
396
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
397
|
+
renderDefault(props),
|
|
398
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
|
|
399
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
400
|
+
"div",
|
|
401
|
+
{
|
|
402
|
+
style: {
|
|
403
|
+
minWidth: 10,
|
|
404
|
+
height: 10,
|
|
405
|
+
borderRadius: "50%",
|
|
406
|
+
backgroundColor: item.color
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
),
|
|
410
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
|
|
411
|
+
] }, item.text)) })
|
|
412
|
+
] });
|
|
413
|
+
};
|
|
414
|
+
var FocusKeywordInput_default = FocusKeywordInput;
|
|
415
|
+
|
|
416
|
+
// src/utils/readability.ts
|
|
417
|
+
function countSyllables(word) {
|
|
418
|
+
var _a;
|
|
419
|
+
const w = word.toLowerCase().replace(/[^a-z]/g, "");
|
|
420
|
+
if (w.length <= 3) return 1;
|
|
421
|
+
const groups = (_a = w.match(/[aeiouy]+/g)) != null ? _a : [];
|
|
422
|
+
let count = groups.length;
|
|
423
|
+
if (w.endsWith("e") && w.length > 1 && !/[aeiouy]/.test(w[w.length - 2])) {
|
|
424
|
+
count = Math.max(1, count - 1);
|
|
425
|
+
}
|
|
426
|
+
return Math.max(1, count);
|
|
427
|
+
}
|
|
428
|
+
function countSentences(text) {
|
|
429
|
+
const matches = text.match(/[.!?]+/g);
|
|
430
|
+
return matches ? matches.length : 1;
|
|
431
|
+
}
|
|
432
|
+
function analyzeReadability(text) {
|
|
433
|
+
const wordList = text.trim().split(/\s+/).filter(Boolean);
|
|
434
|
+
const words = wordList.length;
|
|
435
|
+
if (words < 10) return null;
|
|
436
|
+
const sentences = countSentences(text);
|
|
437
|
+
const syllables = wordList.reduce((acc, word) => acc + countSyllables(word), 0);
|
|
438
|
+
const rawScore = 206.835 - 1.015 * (words / sentences) - 84.6 * (syllables / words);
|
|
439
|
+
const score = Math.round(rawScore * 10) / 10;
|
|
440
|
+
const rawGrade = 0.39 * (words / sentences) + 11.8 * (syllables / words) - 15.59;
|
|
441
|
+
const gradeLevel = Math.round(rawGrade * 10) / 10;
|
|
442
|
+
const avgWordsPerSentence = Math.round(words / sentences * 10) / 10;
|
|
443
|
+
let label;
|
|
444
|
+
let color;
|
|
445
|
+
if (score >= 70) {
|
|
446
|
+
label = "Easy to read";
|
|
447
|
+
color = "green";
|
|
448
|
+
} else if (score >= 50) {
|
|
449
|
+
label = "Fairly easy";
|
|
450
|
+
color = "green";
|
|
451
|
+
} else if (score >= 30) {
|
|
452
|
+
label = "Moderately difficult";
|
|
453
|
+
color = "orange";
|
|
454
|
+
} else {
|
|
455
|
+
label = "Difficult to read";
|
|
456
|
+
color = "red";
|
|
457
|
+
}
|
|
458
|
+
return {
|
|
459
|
+
score,
|
|
460
|
+
gradeLevel,
|
|
461
|
+
avgWordsPerSentence,
|
|
462
|
+
words,
|
|
463
|
+
sentences,
|
|
464
|
+
label,
|
|
465
|
+
color
|
|
466
|
+
};
|
|
467
|
+
}
|
|
12
468
|
var MetaDescription = (props) => {
|
|
13
469
|
const { value, renderDefault, path } = props;
|
|
14
470
|
const parent = sanity.useFormValue([path[0]]);
|
|
@@ -18,6 +474,7 @@ var MetaDescription = (props) => {
|
|
|
18
474
|
() => chunkZBHLMQTS_cjs.getMetaDescriptionValidationMessages(value || "", keywords, isParentseoField),
|
|
19
475
|
[value, keywords, isParentseoField]
|
|
20
476
|
);
|
|
477
|
+
const readability = react.useMemo(() => analyzeReadability(value || ""), [value]);
|
|
21
478
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
22
479
|
renderDefault(props),
|
|
23
480
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 2, children: feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
|
|
@@ -28,7 +485,30 @@ var MetaDescription = (props) => {
|
|
|
28
485
|
}
|
|
29
486
|
),
|
|
30
487
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
|
|
31
|
-
] }, item.text)) })
|
|
488
|
+
] }, item.text)) }),
|
|
489
|
+
readability && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
|
|
490
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
491
|
+
"div",
|
|
492
|
+
{
|
|
493
|
+
style: {
|
|
494
|
+
minWidth: 10,
|
|
495
|
+
height: 10,
|
|
496
|
+
borderRadius: "50%",
|
|
497
|
+
backgroundColor: readability.color
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
),
|
|
501
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { weight: "bold", muted: true, size: 14, children: [
|
|
502
|
+
"Readability: ",
|
|
503
|
+
readability.label,
|
|
504
|
+
" (Flesch ",
|
|
505
|
+
readability.score,
|
|
506
|
+
" \xB7 Grade",
|
|
507
|
+
" ",
|
|
508
|
+
readability.gradeLevel,
|
|
509
|
+
")"
|
|
510
|
+
] })
|
|
511
|
+
] })
|
|
32
512
|
] });
|
|
33
513
|
};
|
|
34
514
|
var MetaDescription_default = MetaDescription;
|
|
@@ -59,8 +539,204 @@ var MetaImage = (props) => {
|
|
|
59
539
|
] });
|
|
60
540
|
};
|
|
61
541
|
var MetaImage_default = MetaImage;
|
|
542
|
+
function resolveImageUrl(asset, projectId, dataset) {
|
|
543
|
+
const ref = asset == null ? void 0 : asset._ref;
|
|
544
|
+
if (!ref) return null;
|
|
545
|
+
const parts = ref.replace("image-", "").split("-");
|
|
546
|
+
const ext = parts[parts.length - 1];
|
|
547
|
+
const dims = parts[parts.length - 2];
|
|
548
|
+
const id = parts.slice(0, parts.length - 2).join("-");
|
|
549
|
+
return `https://cdn.sanity.io/images/${projectId}/${dataset}/${id}-${dims}.${ext}`;
|
|
550
|
+
}
|
|
551
|
+
var MetaTagsPreview = (props) => {
|
|
552
|
+
const { path } = props;
|
|
553
|
+
const [expanded, setExpanded] = react.useState(false);
|
|
554
|
+
const [copyLabel, setCopyLabel] = react.useState("Copy");
|
|
555
|
+
const { scheme } = sanity.useColorScheme();
|
|
556
|
+
const seoFields = sanity.useFormValue([path[0]]);
|
|
557
|
+
const client = sanity.useClient({ apiVersion: "2024-01-01" });
|
|
558
|
+
const { projectId = "", dataset = "" } = client.config();
|
|
559
|
+
const rawHtml = react.useMemo(() => {
|
|
560
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
561
|
+
const lines = [];
|
|
562
|
+
lines.push('<meta charset="UTF-8" />');
|
|
563
|
+
lines.push('<meta name="viewport" content="width=device-width, initial-scale=1" />');
|
|
564
|
+
if (seoFields == null ? void 0 : seoFields.title) lines.push(`<title>${seoFields.title}</title>`);
|
|
565
|
+
if (seoFields == null ? void 0 : seoFields.description)
|
|
566
|
+
lines.push(`<meta name="description" content="${seoFields.description}" />`);
|
|
567
|
+
if (seoFields == null ? void 0 : seoFields.robots) {
|
|
568
|
+
const parts = [];
|
|
569
|
+
if (seoFields.robots.noIndex) parts.push("noindex");
|
|
570
|
+
if (seoFields.robots.noFollow) parts.push("nofollow");
|
|
571
|
+
if (seoFields.robots.noTranslate) parts.push("notranslate");
|
|
572
|
+
if (seoFields.robots.noImageIndex) parts.push("noimageindex");
|
|
573
|
+
if (parts.length) lines.push(`<meta name="robots" content="${parts.join(", ")}" />`);
|
|
574
|
+
}
|
|
575
|
+
if ((_a = seoFields == null ? void 0 : seoFields.keywords) == null ? void 0 : _a.length)
|
|
576
|
+
lines.push(`<meta name="keywords" content="${seoFields.keywords.join(", ")}" />`);
|
|
577
|
+
if (seoFields == null ? void 0 : seoFields.canonicalUrl)
|
|
578
|
+
lines.push(`<link rel="canonical" href="${seoFields.canonicalUrl}" />`);
|
|
579
|
+
const og = seoFields == null ? void 0 : seoFields.openGraph;
|
|
580
|
+
if (og == null ? void 0 : og.type) lines.push(`<meta property="og:type" content="${og.type}" />`);
|
|
581
|
+
if (og == null ? void 0 : og.title) lines.push(`<meta property="og:title" content="${og.title}" />`);
|
|
582
|
+
if (og == null ? void 0 : og.description)
|
|
583
|
+
lines.push(`<meta property="og:description" content="${og.description}" />`);
|
|
584
|
+
if (og == null ? void 0 : og.siteName) lines.push(`<meta property="og:site_name" content="${og.siteName}" />`);
|
|
585
|
+
if (og == null ? void 0 : og.url) lines.push(`<meta property="og:url" content="${og.url}" />`);
|
|
586
|
+
const ogImg = (og == null ? void 0 : og.imageUrl) || resolveImageUrl((_b = og == null ? void 0 : og.image) == null ? void 0 : _b.asset, projectId, dataset) || resolveImageUrl((_c = seoFields == null ? void 0 : seoFields.metaImage) == null ? void 0 : _c.asset, projectId, dataset);
|
|
587
|
+
if (ogImg) lines.push(`<meta property="og:image" content="${ogImg}" />`);
|
|
588
|
+
const tw = seoFields == null ? void 0 : seoFields.twitter;
|
|
589
|
+
if (tw == null ? void 0 : tw.card) lines.push(`<meta name="twitter:card" content="${tw.card}" />`);
|
|
590
|
+
if (tw == null ? void 0 : tw.site) lines.push(`<meta name="twitter:site" content="${tw.site}" />`);
|
|
591
|
+
if (tw == null ? void 0 : tw.creator) lines.push(`<meta name="twitter:creator" content="${tw.creator}" />`);
|
|
592
|
+
if (tw == null ? void 0 : tw.title) lines.push(`<meta name="twitter:title" content="${tw.title}" />`);
|
|
593
|
+
if (tw == null ? void 0 : tw.description)
|
|
594
|
+
lines.push(`<meta name="twitter:description" content="${tw.description}" />`);
|
|
595
|
+
const twImg = (tw == null ? void 0 : tw.imageUrl) || resolveImageUrl((_d = tw == null ? void 0 : tw.image) == null ? void 0 : _d.asset, projectId, dataset);
|
|
596
|
+
if (twImg) lines.push(`<meta name="twitter:image" content="${twImg}" />`);
|
|
597
|
+
if ((_e = seoFields == null ? void 0 : seoFields.hreflangs) == null ? void 0 : _e.length) {
|
|
598
|
+
for (const e of seoFields.hreflangs) {
|
|
599
|
+
if (e.locale && e.url)
|
|
600
|
+
lines.push(`<link rel="alternate" hreflang="${e.locale}" href="${e.url}" />`);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if ((_f = seoFields == null ? void 0 : seoFields.metaAttributes) == null ? void 0 : _f.length) {
|
|
604
|
+
for (const attr of seoFields.metaAttributes) {
|
|
605
|
+
if (attr.key && attr.type === "string" && attr.value) {
|
|
606
|
+
lines.push(`<meta name="${attr.key}" content="${attr.value}" />`);
|
|
607
|
+
} else if (attr.key && attr.type === "image" && ((_g = attr.image) == null ? void 0 : _g.asset)) {
|
|
608
|
+
const imgUrl = resolveImageUrl(attr.image.asset, projectId, dataset);
|
|
609
|
+
if (imgUrl) lines.push(`<meta name="${attr.key}" content="${imgUrl}" />`);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return lines.join("\n");
|
|
614
|
+
}, [seoFields, projectId, dataset]);
|
|
615
|
+
const tagCount = react.useMemo(() => rawHtml.split("\n").filter(Boolean).length, [rawHtml]);
|
|
616
|
+
const tokens = react.useMemo(() => chunkB5IVI5LP_cjs.tokenizeHtml(rawHtml, scheme), [rawHtml, scheme]);
|
|
617
|
+
const handleCopy = () => {
|
|
618
|
+
navigator.clipboard.writeText(rawHtml).then(() => {
|
|
619
|
+
setCopyLabel("Copied!");
|
|
620
|
+
setTimeout(() => setCopyLabel("Copy"), 2e3);
|
|
621
|
+
});
|
|
622
|
+
};
|
|
623
|
+
const isDark = scheme === "dark";
|
|
624
|
+
const codeBg = isDark ? "#161b22" : "#f6f8fa";
|
|
625
|
+
const codeBorder = isDark ? "#30363d" : "#d0d7de";
|
|
626
|
+
const headerBg = isDark ? "#21262d" : "#f0f2f4";
|
|
627
|
+
const headerBorder = isDark ? "#30363d" : "#d0d7de";
|
|
628
|
+
const headerText = isDark ? "#e6edf3" : "#24292f";
|
|
629
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 3, radius: 2, tone: "default", border: true, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
630
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", justify: "space-between", gap: 3, children: [
|
|
631
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "semibold", size: 1, children: "Meta Tags Preview" }),
|
|
632
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { gap: 2, align: "center", children: [
|
|
633
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: 0, muted: true, children: [
|
|
634
|
+
tagCount,
|
|
635
|
+
" tags generated"
|
|
636
|
+
] }),
|
|
637
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
638
|
+
ui.Button,
|
|
639
|
+
{
|
|
640
|
+
text: copyLabel,
|
|
641
|
+
tone: "default",
|
|
642
|
+
mode: "ghost",
|
|
643
|
+
fontSize: 1,
|
|
644
|
+
padding: 2,
|
|
645
|
+
onClick: handleCopy
|
|
646
|
+
}
|
|
647
|
+
)
|
|
648
|
+
] })
|
|
649
|
+
] }),
|
|
650
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
651
|
+
"button",
|
|
652
|
+
{
|
|
653
|
+
type: "button",
|
|
654
|
+
onClick: () => setExpanded((p) => !p),
|
|
655
|
+
style: {
|
|
656
|
+
display: "flex",
|
|
657
|
+
alignItems: "center",
|
|
658
|
+
justifyContent: "center",
|
|
659
|
+
gap: 6,
|
|
660
|
+
width: "100%",
|
|
661
|
+
background: headerBg,
|
|
662
|
+
border: `1px solid ${headerBorder}`,
|
|
663
|
+
borderRadius: 6,
|
|
664
|
+
padding: "6px 12px",
|
|
665
|
+
cursor: "pointer",
|
|
666
|
+
fontSize: 12,
|
|
667
|
+
fontWeight: 500,
|
|
668
|
+
color: headerText
|
|
669
|
+
},
|
|
670
|
+
children: [
|
|
671
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 10 }, children: expanded ? "\u25B2" : "\u25BC" }),
|
|
672
|
+
expanded ? "Hide tags" : "Show tags"
|
|
673
|
+
]
|
|
674
|
+
}
|
|
675
|
+
),
|
|
676
|
+
expanded && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
677
|
+
"div",
|
|
678
|
+
{
|
|
679
|
+
style: {
|
|
680
|
+
borderRadius: 6,
|
|
681
|
+
border: `1px solid ${codeBorder}`,
|
|
682
|
+
overflow: "hidden"
|
|
683
|
+
},
|
|
684
|
+
children: [
|
|
685
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
686
|
+
"div",
|
|
687
|
+
{
|
|
688
|
+
style: {
|
|
689
|
+
background: headerBg,
|
|
690
|
+
borderBottom: `1px solid ${headerBorder}`,
|
|
691
|
+
padding: "6px 14px",
|
|
692
|
+
display: "flex",
|
|
693
|
+
alignItems: "center",
|
|
694
|
+
gap: 6
|
|
695
|
+
},
|
|
696
|
+
children: [
|
|
697
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
698
|
+
"span",
|
|
699
|
+
{
|
|
700
|
+
style: {
|
|
701
|
+
width: 8,
|
|
702
|
+
height: 8,
|
|
703
|
+
borderRadius: "50%",
|
|
704
|
+
background: isDark ? "#388bfd" : "#0550ae",
|
|
705
|
+
display: "inline-block"
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
),
|
|
709
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 11, color: headerText, fontFamily: "monospace" }, children: "HTML" })
|
|
710
|
+
]
|
|
711
|
+
}
|
|
712
|
+
),
|
|
713
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
714
|
+
ui.Box,
|
|
715
|
+
{
|
|
716
|
+
as: "pre",
|
|
717
|
+
padding: 3,
|
|
718
|
+
style: {
|
|
719
|
+
margin: 0,
|
|
720
|
+
maxHeight: 420,
|
|
721
|
+
overflow: "auto",
|
|
722
|
+
fontSize: 12,
|
|
723
|
+
fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
|
|
724
|
+
lineHeight: 1.7,
|
|
725
|
+
whiteSpace: "pre-wrap",
|
|
726
|
+
wordBreak: "break-word",
|
|
727
|
+
backgroundColor: codeBg
|
|
728
|
+
},
|
|
729
|
+
children: tokens.map((token, idx) => /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: token.color }, children: token.text }, idx))
|
|
730
|
+
}
|
|
731
|
+
)
|
|
732
|
+
]
|
|
733
|
+
}
|
|
734
|
+
)
|
|
735
|
+
] }) });
|
|
736
|
+
};
|
|
737
|
+
var MetaTagsPreview_default = MetaTagsPreview;
|
|
62
738
|
var MetaTitle = (props) => {
|
|
63
|
-
var _a, _b;
|
|
739
|
+
var _a, _b, _c;
|
|
64
740
|
const { value, renderDefault, path, schemaType } = props;
|
|
65
741
|
const { options } = schemaType;
|
|
66
742
|
const parent = sanity.useFormValue([path[0]]);
|
|
@@ -69,6 +745,7 @@ var MetaTitle = (props) => {
|
|
|
69
745
|
const rootDoc = (_a = sanity.useFormValue([])) != null ? _a : {};
|
|
70
746
|
const client = sanity.useClient({ apiVersion: (_b = options == null ? void 0 : options.apiVersion) != null ? _b : "2024-01-01" });
|
|
71
747
|
const [groqTitleSuffix, setGroqTitleSuffix] = react.useState("");
|
|
748
|
+
const [isDuplicateTitle, setIsDuplicateTitle] = react.useState(false);
|
|
72
749
|
const titleSuffixQuery = options == null ? void 0 : options.titleSuffixQuery;
|
|
73
750
|
const titleSuffixOption = options == null ? void 0 : options.titleSuffix;
|
|
74
751
|
react.useEffect(() => {
|
|
@@ -79,6 +756,21 @@ var MetaTitle = (props) => {
|
|
|
79
756
|
setGroqTitleSuffix("");
|
|
80
757
|
});
|
|
81
758
|
}, [titleSuffixQuery, client]);
|
|
759
|
+
const currentDocId = (_c = rootDoc._id) != null ? _c : "";
|
|
760
|
+
react.useEffect(() => {
|
|
761
|
+
if (!(value == null ? void 0 : value.trim()) || !currentDocId) {
|
|
762
|
+
setIsDuplicateTitle(false);
|
|
763
|
+
return () => {
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
const timer = setTimeout(() => {
|
|
767
|
+
client.fetch(
|
|
768
|
+
`count(*[seo.title == $title && _id != $id && !(_id in path("drafts.**"))])`,
|
|
769
|
+
{ title: value, id: currentDocId }
|
|
770
|
+
).then((count) => setIsDuplicateTitle(count > 0)).catch(() => setIsDuplicateTitle(false));
|
|
771
|
+
}, 600);
|
|
772
|
+
return () => clearTimeout(timer);
|
|
773
|
+
}, [value, client, currentDocId]);
|
|
82
774
|
const resolvedSuffix = react.useMemo(() => {
|
|
83
775
|
if (titleSuffixQuery) return groqTitleSuffix;
|
|
84
776
|
if (!titleSuffixOption) return "";
|
|
@@ -94,20 +786,36 @@ var MetaTitle = (props) => {
|
|
|
94
786
|
);
|
|
95
787
|
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
|
|
96
788
|
renderDefault(props),
|
|
97
|
-
/* @__PURE__ */ jsxRuntime.
|
|
98
|
-
/* @__PURE__ */ jsxRuntime.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
789
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 2, children: [
|
|
790
|
+
feedbackItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
|
|
791
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
792
|
+
"div",
|
|
793
|
+
{
|
|
794
|
+
style: {
|
|
795
|
+
minWidth: 10,
|
|
796
|
+
height: 10,
|
|
797
|
+
borderRadius: "50%",
|
|
798
|
+
backgroundColor: item.color
|
|
799
|
+
}
|
|
106
800
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
801
|
+
),
|
|
802
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: item.text })
|
|
803
|
+
] }, item.text)),
|
|
804
|
+
isDuplicateTitle && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 7 }, children: [
|
|
805
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
806
|
+
"div",
|
|
807
|
+
{
|
|
808
|
+
style: {
|
|
809
|
+
minWidth: 10,
|
|
810
|
+
height: 10,
|
|
811
|
+
borderRadius: "50%",
|
|
812
|
+
backgroundColor: "orange"
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
),
|
|
816
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "bold", muted: true, size: 14, children: "Duplicate meta title \u2014 another published document uses this exact title." })
|
|
817
|
+
] })
|
|
818
|
+
] })
|
|
111
819
|
] });
|
|
112
820
|
};
|
|
113
821
|
var MetaTitle_default = MetaTitle;
|
|
@@ -136,7 +844,7 @@ var DEFAULT_FIELD_INFO = {
|
|
|
136
844
|
},
|
|
137
845
|
robots: {
|
|
138
846
|
title: "Robots Settings",
|
|
139
|
-
description: "Configure how search engine crawlers should index
|
|
847
|
+
description: "Configure how search engine crawlers should index, follow links, translate content, and index images on this page."
|
|
140
848
|
},
|
|
141
849
|
metaAttributes: {
|
|
142
850
|
title: "Additional Meta Attributes",
|
|
@@ -205,6 +913,22 @@ var DEFAULT_FIELD_INFO = {
|
|
|
205
913
|
twitterImageUrl: {
|
|
206
914
|
title: "X Image URL",
|
|
207
915
|
description: "Enter the full URL of the image for X (formerly Twitter). Ensure the image is accessible and meets the recommended size."
|
|
916
|
+
},
|
|
917
|
+
focusKeyword: {
|
|
918
|
+
title: "Focus Keyword",
|
|
919
|
+
description: "The primary keyword you want this page to rank for. Used to check keyword placement in title, description, and URL."
|
|
920
|
+
},
|
|
921
|
+
hreflangs: {
|
|
922
|
+
title: "Hreflang Entries",
|
|
923
|
+
description: "Add alternate language/region versions of this page. Include x-default for the fallback URL."
|
|
924
|
+
},
|
|
925
|
+
geoChecklist: {
|
|
926
|
+
title: "AI Overview Readiness",
|
|
927
|
+
description: "Checklist of signals that improve visibility in AI-generated overviews."
|
|
928
|
+
},
|
|
929
|
+
metaTagsPreview: {
|
|
930
|
+
title: "Meta Tags Preview",
|
|
931
|
+
description: "Preview the full HTML <head> meta tags generated for this page."
|
|
208
932
|
}
|
|
209
933
|
};
|
|
210
934
|
var getFieldInfo = (fieldName, fieldOverrides) => {
|
|
@@ -350,14 +1074,14 @@ function openGraph(config = {}) {
|
|
|
350
1074
|
title: "Open Graph Settings",
|
|
351
1075
|
type: "object",
|
|
352
1076
|
fields: [
|
|
353
|
-
sanity.defineField(
|
|
1077
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
354
1078
|
name: "url",
|
|
355
1079
|
type: "url"
|
|
356
1080
|
}, getFieldInfo("openGraphUrl", config.fieldOverrides)), {
|
|
357
1081
|
hidden: getFieldHiddenFunction("openGraphUrl", config),
|
|
358
1082
|
description: "The canonical URL of the page. This should be the full URL including protocol (https://)."
|
|
359
1083
|
})),
|
|
360
|
-
sanity.defineField(
|
|
1084
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
361
1085
|
name: "title"
|
|
362
1086
|
}, getFieldInfo("openGraphTitle", config.fieldOverrides)), {
|
|
363
1087
|
type: "string",
|
|
@@ -367,7 +1091,7 @@ function openGraph(config = {}) {
|
|
|
367
1091
|
// Can also wrap with a string input + preview
|
|
368
1092
|
}
|
|
369
1093
|
})),
|
|
370
|
-
sanity.defineField(
|
|
1094
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
371
1095
|
name: "description"
|
|
372
1096
|
}, getFieldInfo("openGraphDescription", config.fieldOverrides)), {
|
|
373
1097
|
type: "text",
|
|
@@ -378,13 +1102,13 @@ function openGraph(config = {}) {
|
|
|
378
1102
|
// Can also wrap with a text area + preview
|
|
379
1103
|
}
|
|
380
1104
|
})),
|
|
381
|
-
sanity.defineField(
|
|
1105
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
382
1106
|
name: "siteName"
|
|
383
1107
|
}, getFieldInfo("openGraphSiteName", config.fieldOverrides)), {
|
|
384
1108
|
type: "string",
|
|
385
1109
|
hidden: getFieldHiddenFunction("openGraphSiteName", config)
|
|
386
1110
|
})),
|
|
387
|
-
sanity.defineField(
|
|
1111
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
388
1112
|
name: "type"
|
|
389
1113
|
}, getFieldInfo("openGraphType", config.fieldOverrides)), {
|
|
390
1114
|
type: "string",
|
|
@@ -403,7 +1127,7 @@ function openGraph(config = {}) {
|
|
|
403
1127
|
hidden: getFieldHiddenFunction("openGraphType", config),
|
|
404
1128
|
initialValue: "website"
|
|
405
1129
|
})),
|
|
406
|
-
sanity.defineField(
|
|
1130
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
407
1131
|
name: "imageType"
|
|
408
1132
|
}, getFieldInfo("openGraphImageType", config.fieldOverrides)), {
|
|
409
1133
|
type: "string",
|
|
@@ -416,7 +1140,7 @@ function openGraph(config = {}) {
|
|
|
416
1140
|
hidden: getFieldHiddenFunction("openGraphImage", config),
|
|
417
1141
|
initialValue: "upload"
|
|
418
1142
|
})),
|
|
419
|
-
sanity.defineField(
|
|
1143
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
420
1144
|
name: "image"
|
|
421
1145
|
}, getFieldInfo("openGraphImage", config.fieldOverrides)), {
|
|
422
1146
|
type: "image",
|
|
@@ -441,7 +1165,7 @@ function openGraph(config = {}) {
|
|
|
441
1165
|
return typeof hiddenFn === "function" ? hiddenFn(context) : hiddenFn;
|
|
442
1166
|
}
|
|
443
1167
|
})),
|
|
444
|
-
sanity.defineField(
|
|
1168
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
445
1169
|
name: "imageUrl"
|
|
446
1170
|
}, getFieldInfo("openGraphImageUrl", config.fieldOverrides)), {
|
|
447
1171
|
type: "url",
|
|
@@ -577,7 +1301,7 @@ function twitter(config = {}) {
|
|
|
577
1301
|
title: "X (Formerly Twitter)",
|
|
578
1302
|
type: "object",
|
|
579
1303
|
fields: [
|
|
580
|
-
sanity.defineField(
|
|
1304
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
581
1305
|
name: "card"
|
|
582
1306
|
}, getFieldInfo("twitterCard", config.fieldOverrides)), {
|
|
583
1307
|
type: "string",
|
|
@@ -593,19 +1317,19 @@ function twitter(config = {}) {
|
|
|
593
1317
|
initialValue: "summary_large_image"
|
|
594
1318
|
// good default
|
|
595
1319
|
})),
|
|
596
|
-
sanity.defineField(
|
|
1320
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
597
1321
|
name: "site"
|
|
598
1322
|
}, getFieldInfo("twitterSite", config.fieldOverrides)), {
|
|
599
1323
|
type: "string",
|
|
600
1324
|
hidden: getFieldHiddenFunction("twitterSite", config)
|
|
601
1325
|
})),
|
|
602
|
-
sanity.defineField(
|
|
1326
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
603
1327
|
name: "creator",
|
|
604
1328
|
type: "string"
|
|
605
1329
|
}, getFieldInfo("twitterCreator", config.fieldOverrides)), {
|
|
606
1330
|
hidden: getFieldHiddenFunction("twitterCreator", config)
|
|
607
1331
|
})),
|
|
608
|
-
sanity.defineField(
|
|
1332
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
609
1333
|
name: "title",
|
|
610
1334
|
type: "string"
|
|
611
1335
|
}, getFieldInfo("twitterTitle", config.fieldOverrides)), {
|
|
@@ -614,7 +1338,7 @@ function twitter(config = {}) {
|
|
|
614
1338
|
input: twitterTitle_default
|
|
615
1339
|
}
|
|
616
1340
|
})),
|
|
617
|
-
sanity.defineField(
|
|
1341
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
618
1342
|
name: "description",
|
|
619
1343
|
type: "text",
|
|
620
1344
|
rows: 3
|
|
@@ -624,7 +1348,7 @@ function twitter(config = {}) {
|
|
|
624
1348
|
input: twitterDescription_default
|
|
625
1349
|
}
|
|
626
1350
|
})),
|
|
627
|
-
sanity.defineField(
|
|
1351
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
628
1352
|
name: "imageType"
|
|
629
1353
|
}, getFieldInfo("twitterImageType", config.fieldOverrides)), {
|
|
630
1354
|
type: "string",
|
|
@@ -637,7 +1361,7 @@ function twitter(config = {}) {
|
|
|
637
1361
|
hidden: getFieldHiddenFunction("twitterImage", config),
|
|
638
1362
|
initialValue: "upload"
|
|
639
1363
|
})),
|
|
640
|
-
sanity.defineField(
|
|
1364
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
641
1365
|
name: "image"
|
|
642
1366
|
}, getFieldInfo("twitterImage", config.fieldOverrides)), {
|
|
643
1367
|
type: "image",
|
|
@@ -662,7 +1386,7 @@ function twitter(config = {}) {
|
|
|
662
1386
|
return typeof hiddenFn === "function" ? hiddenFn(context) : hiddenFn;
|
|
663
1387
|
}
|
|
664
1388
|
})),
|
|
665
|
-
sanity.defineField(
|
|
1389
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
666
1390
|
name: "imageUrl"
|
|
667
1391
|
}, getFieldInfo("twitterImageUrl", config.fieldOverrides)), {
|
|
668
1392
|
type: "url",
|
|
@@ -681,7 +1405,7 @@ function twitter(config = {}) {
|
|
|
681
1405
|
}
|
|
682
1406
|
|
|
683
1407
|
// src/schemas/index.ts
|
|
684
|
-
var LazySeoPreview = react.lazy(() => import('./SeoPreview-
|
|
1408
|
+
var LazySeoPreview = react.lazy(() => import('./SeoPreview-3EXR6FD4.cjs'));
|
|
685
1409
|
var SeoPreviewWrapper = (props) => react.createElement(react.Suspense, { fallback: null }, react.createElement(LazySeoPreview, props));
|
|
686
1410
|
function buildFieldGroupMap(groups) {
|
|
687
1411
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -714,13 +1438,13 @@ function withGroup(field, fieldGroupMap) {
|
|
|
714
1438
|
if (!fieldGroupMap) return field;
|
|
715
1439
|
const groups = fieldGroupMap.get(field.name);
|
|
716
1440
|
if (!groups || groups.length === 0) return field;
|
|
717
|
-
return
|
|
1441
|
+
return chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, field), { group: groups.length === 1 ? groups[0] : groups });
|
|
718
1442
|
}
|
|
719
1443
|
function seoFieldsSchema(config = {}) {
|
|
720
1444
|
const groupsCfg = config.fieldGroups;
|
|
721
1445
|
const fieldGroupMap = (groupsCfg == null ? void 0 : groupsCfg.length) ? buildFieldGroupMap(groupsCfg) : void 0;
|
|
722
1446
|
const sanityGroups = (groupsCfg == null ? void 0 : groupsCfg.length) ? toSanityGroups(groupsCfg) : void 0;
|
|
723
|
-
return sanity.defineType(
|
|
1447
|
+
return sanity.defineType(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
724
1448
|
name: "seoFields",
|
|
725
1449
|
title: "SEO Fields",
|
|
726
1450
|
type: "object"
|
|
@@ -743,7 +1467,7 @@ function seoFieldsSchema(config = {}) {
|
|
|
743
1467
|
title: "SEO Preview",
|
|
744
1468
|
type: "string",
|
|
745
1469
|
components: { input: SeoPreviewWrapper },
|
|
746
|
-
options:
|
|
1470
|
+
options: chunk254YHUN3_cjs.__spreadValues(chunk254YHUN3_cjs.__spreadValues(chunk254YHUN3_cjs.__spreadValues(chunk254YHUN3_cjs.__spreadValues(chunk254YHUN3_cjs.__spreadValues({
|
|
747
1471
|
baseUrl: config.baseUrl || "https://www.example.com"
|
|
748
1472
|
}, config.apiVersion ? { apiVersion: config.apiVersion } : {}), typeof config.seoPreview === "object" && config.seoPreview && config.seoPreview.prefix ? { prefix: config.seoPreview.prefix } : {}), typeof config.seoPreview === "object" && config.seoPreview && config.seoPreview.titleSuffix ? { titleSuffix: config.seoPreview.titleSuffix } : {}), typeof config.seoPreview === "object" && config.seoPreview && config.seoPreview.titleSuffixInheritColor ? { titleSuffixInheritColor: config.seoPreview.titleSuffixInheritColor } : {}), typeof config.seoPreview === "object" && config.seoPreview && config.seoPreview.titleSuffixQuery ? { titleSuffixQuery: config.seoPreview.titleSuffixQuery } : {}),
|
|
749
1473
|
initialValue: "",
|
|
@@ -753,20 +1477,20 @@ function seoFieldsSchema(config = {}) {
|
|
|
753
1477
|
)
|
|
754
1478
|
] : [],
|
|
755
1479
|
withGroup(
|
|
756
|
-
sanity.defineField(
|
|
1480
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
757
1481
|
name: "title"
|
|
758
1482
|
}, getFieldInfo("title", config.fieldOverrides)), {
|
|
759
1483
|
type: "string",
|
|
760
1484
|
components: {
|
|
761
1485
|
input: MetaTitle_default
|
|
762
1486
|
},
|
|
763
|
-
options:
|
|
1487
|
+
options: chunk254YHUN3_cjs.__spreadValues(chunk254YHUN3_cjs.__spreadValues(chunk254YHUN3_cjs.__spreadValues({}, config.apiVersion ? { apiVersion: config.apiVersion } : {}), typeof config.seoPreview === "object" && config.seoPreview && config.seoPreview.titleSuffix ? { titleSuffix: config.seoPreview.titleSuffix } : {}), typeof config.seoPreview === "object" && config.seoPreview && config.seoPreview.titleSuffixQuery ? { titleSuffixQuery: config.seoPreview.titleSuffixQuery } : {}),
|
|
764
1488
|
hidden: getFieldHiddenFunction("title", config)
|
|
765
1489
|
})),
|
|
766
1490
|
fieldGroupMap
|
|
767
1491
|
),
|
|
768
1492
|
withGroup(
|
|
769
|
-
sanity.defineField(
|
|
1493
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
770
1494
|
name: "description"
|
|
771
1495
|
}, getFieldInfo("description", config.fieldOverrides)), {
|
|
772
1496
|
type: "text",
|
|
@@ -779,7 +1503,7 @@ function seoFieldsSchema(config = {}) {
|
|
|
779
1503
|
fieldGroupMap
|
|
780
1504
|
),
|
|
781
1505
|
withGroup(
|
|
782
|
-
sanity.defineField(
|
|
1506
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
783
1507
|
name: "metaImage"
|
|
784
1508
|
}, getFieldInfo("metaImage", config.fieldOverrides)), {
|
|
785
1509
|
type: "image",
|
|
@@ -794,7 +1518,7 @@ function seoFieldsSchema(config = {}) {
|
|
|
794
1518
|
fieldGroupMap
|
|
795
1519
|
),
|
|
796
1520
|
withGroup(
|
|
797
|
-
sanity.defineField(
|
|
1521
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
798
1522
|
name: "metaAttributes"
|
|
799
1523
|
}, getFieldInfo("metaAttributes", config.fieldOverrides)), {
|
|
800
1524
|
type: "array",
|
|
@@ -804,7 +1528,7 @@ function seoFieldsSchema(config = {}) {
|
|
|
804
1528
|
fieldGroupMap
|
|
805
1529
|
),
|
|
806
1530
|
withGroup(
|
|
807
|
-
sanity.defineField(
|
|
1531
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
808
1532
|
name: "keywords"
|
|
809
1533
|
}, getFieldInfo("keywords", config.fieldOverrides)), {
|
|
810
1534
|
title: "Keywords",
|
|
@@ -816,7 +1540,7 @@ function seoFieldsSchema(config = {}) {
|
|
|
816
1540
|
fieldGroupMap
|
|
817
1541
|
),
|
|
818
1542
|
withGroup(
|
|
819
|
-
sanity.defineField(
|
|
1543
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
820
1544
|
name: "canonicalUrl"
|
|
821
1545
|
}, getFieldInfo("canonicalUrl", config.fieldOverrides)), {
|
|
822
1546
|
title: "Canonical URL",
|
|
@@ -826,6 +1550,60 @@ function seoFieldsSchema(config = {}) {
|
|
|
826
1550
|
})),
|
|
827
1551
|
fieldGroupMap
|
|
828
1552
|
),
|
|
1553
|
+
withGroup(
|
|
1554
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
1555
|
+
name: "focusKeyword"
|
|
1556
|
+
}, getFieldInfo("focusKeyword", config.fieldOverrides)), {
|
|
1557
|
+
type: "string",
|
|
1558
|
+
components: {
|
|
1559
|
+
input: FocusKeywordInput_default
|
|
1560
|
+
},
|
|
1561
|
+
hidden: getFieldHiddenFunction("focusKeyword", config)
|
|
1562
|
+
})),
|
|
1563
|
+
fieldGroupMap
|
|
1564
|
+
),
|
|
1565
|
+
withGroup(
|
|
1566
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
1567
|
+
name: "hreflangs"
|
|
1568
|
+
}, getFieldInfo("hreflangs", config.fieldOverrides)), {
|
|
1569
|
+
type: "array",
|
|
1570
|
+
of: [{ type: "hreflangEntry" }],
|
|
1571
|
+
description: "Add alternate language/region versions. Include x-default for the fallback URL.",
|
|
1572
|
+
hidden: getFieldHiddenFunction("hreflangs", config)
|
|
1573
|
+
})),
|
|
1574
|
+
fieldGroupMap
|
|
1575
|
+
),
|
|
1576
|
+
...config.geo === false ? [] : [
|
|
1577
|
+
withGroup(
|
|
1578
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
1579
|
+
name: "geoChecklist"
|
|
1580
|
+
}, getFieldInfo("geoChecklist", config.fieldOverrides)), {
|
|
1581
|
+
type: "string",
|
|
1582
|
+
readOnly: true,
|
|
1583
|
+
components: {
|
|
1584
|
+
input: GEOChecklist_default
|
|
1585
|
+
},
|
|
1586
|
+
options: chunk254YHUN3_cjs.__spreadValues({}, config.licenseKey ? { licenseKey: config.licenseKey } : {}),
|
|
1587
|
+
hidden: getFieldHiddenFunction("geoChecklist", config)
|
|
1588
|
+
})),
|
|
1589
|
+
fieldGroupMap
|
|
1590
|
+
)
|
|
1591
|
+
],
|
|
1592
|
+
...config.metaTagsPreview === false ? [] : [
|
|
1593
|
+
withGroup(
|
|
1594
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
1595
|
+
name: "metaTagsPreview"
|
|
1596
|
+
}, getFieldInfo("metaTagsPreview", config.fieldOverrides)), {
|
|
1597
|
+
type: "string",
|
|
1598
|
+
readOnly: true,
|
|
1599
|
+
components: {
|
|
1600
|
+
input: MetaTagsPreview_default
|
|
1601
|
+
},
|
|
1602
|
+
hidden: getFieldHiddenFunction("metaTagsPreview", config)
|
|
1603
|
+
})),
|
|
1604
|
+
fieldGroupMap
|
|
1605
|
+
)
|
|
1606
|
+
],
|
|
829
1607
|
withGroup(openGraph(config), fieldGroupMap),
|
|
830
1608
|
withGroup(twitter(config), fieldGroupMap)
|
|
831
1609
|
]
|
|
@@ -837,7 +1615,7 @@ function baseMeta(config = {}) {
|
|
|
837
1615
|
title: "Basic Meta Settings",
|
|
838
1616
|
type: "object",
|
|
839
1617
|
fields: [
|
|
840
|
-
sanity.defineField(
|
|
1618
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
841
1619
|
name: "title"
|
|
842
1620
|
}, getFieldInfo("title", config.fieldOverrides)), {
|
|
843
1621
|
type: "string",
|
|
@@ -846,7 +1624,7 @@ function baseMeta(config = {}) {
|
|
|
846
1624
|
},
|
|
847
1625
|
hidden: getFieldHiddenFunction("title", config)
|
|
848
1626
|
})),
|
|
849
|
-
sanity.defineField(
|
|
1627
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
850
1628
|
name: "description"
|
|
851
1629
|
}, getFieldInfo("description", config.fieldOverrides)), {
|
|
852
1630
|
type: "text",
|
|
@@ -856,7 +1634,7 @@ function baseMeta(config = {}) {
|
|
|
856
1634
|
},
|
|
857
1635
|
hidden: getFieldHiddenFunction("description", config)
|
|
858
1636
|
})),
|
|
859
|
-
sanity.defineField(
|
|
1637
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
860
1638
|
name: "metaImage"
|
|
861
1639
|
}, getFieldInfo("metaImage", config.fieldOverrides)), {
|
|
862
1640
|
type: "image",
|
|
@@ -868,7 +1646,7 @@ function baseMeta(config = {}) {
|
|
|
868
1646
|
},
|
|
869
1647
|
hidden: getFieldHiddenFunction("metaImage", config)
|
|
870
1648
|
})),
|
|
871
|
-
sanity.defineField(
|
|
1649
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
872
1650
|
name: "keywords"
|
|
873
1651
|
}, getFieldInfo("keywords", config.fieldOverrides)), {
|
|
874
1652
|
title: "Keywords",
|
|
@@ -877,7 +1655,7 @@ function baseMeta(config = {}) {
|
|
|
877
1655
|
description: "Add relevant keywords for this page. These keywords will be used for SEO purposes.",
|
|
878
1656
|
hidden: getFieldHiddenFunction("keywords", config)
|
|
879
1657
|
})),
|
|
880
|
-
sanity.defineField(
|
|
1658
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
881
1659
|
name: "canonicalUrl"
|
|
882
1660
|
}, getFieldInfo("canonicalUrl", config.fieldOverrides)), {
|
|
883
1661
|
title: "Canonical URL",
|
|
@@ -885,7 +1663,7 @@ function baseMeta(config = {}) {
|
|
|
885
1663
|
description: "Specify the canonical URL for this page. This helps prevent duplicate content issues by indicating the preferred version of a page.",
|
|
886
1664
|
hidden: getFieldHiddenFunction("canonicalUrl", config)
|
|
887
1665
|
})),
|
|
888
|
-
sanity.defineField(
|
|
1666
|
+
sanity.defineField(chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({
|
|
889
1667
|
name: "metaAttributes"
|
|
890
1668
|
}, getFieldInfo("metaAttributes", config.fieldOverrides)), {
|
|
891
1669
|
type: "array",
|
|
@@ -895,6 +1673,38 @@ function baseMeta(config = {}) {
|
|
|
895
1673
|
]
|
|
896
1674
|
});
|
|
897
1675
|
}
|
|
1676
|
+
var hreflang_default = sanity.defineType({
|
|
1677
|
+
name: "hreflangEntry",
|
|
1678
|
+
title: "Hreflang Entry",
|
|
1679
|
+
type: "object",
|
|
1680
|
+
fields: [
|
|
1681
|
+
sanity.defineField({
|
|
1682
|
+
name: "locale",
|
|
1683
|
+
title: "Language / Region",
|
|
1684
|
+
type: "string",
|
|
1685
|
+
description: "BCP 47 tag \u2014 e.g. en, fr-FR, x-default",
|
|
1686
|
+
validation: (Rule) => Rule.required().custom((value) => {
|
|
1687
|
+
if (!value) return "Required";
|
|
1688
|
+
if (!/^(x-default|[a-z]{2,3}(-[A-Z]{2,3})?)$/.test(value)) {
|
|
1689
|
+
return "Must be a valid BCP 47 tag (e.g. en, fr-FR, x-default)";
|
|
1690
|
+
}
|
|
1691
|
+
return true;
|
|
1692
|
+
})
|
|
1693
|
+
}),
|
|
1694
|
+
sanity.defineField({
|
|
1695
|
+
name: "url",
|
|
1696
|
+
title: "URL",
|
|
1697
|
+
type: "url",
|
|
1698
|
+
validation: (Rule) => Rule.required().uri({ scheme: ["http", "https"] })
|
|
1699
|
+
})
|
|
1700
|
+
],
|
|
1701
|
+
preview: {
|
|
1702
|
+
select: {
|
|
1703
|
+
title: "locale",
|
|
1704
|
+
subtitle: "url"
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
});
|
|
898
1708
|
var metaAttribute_default = sanity.defineType({
|
|
899
1709
|
name: "metaAttribute",
|
|
900
1710
|
title: "Meta Attribute",
|
|
@@ -985,9 +1795,23 @@ var robots_default = sanity.defineType({
|
|
|
985
1795
|
type: "boolean",
|
|
986
1796
|
initialValue: false,
|
|
987
1797
|
description: "Enable this to prevent search engines from following links on this page. Links will not pass SEO value."
|
|
1798
|
+
}),
|
|
1799
|
+
sanity.defineField({
|
|
1800
|
+
name: "noTranslate",
|
|
1801
|
+
title: "No Translate",
|
|
1802
|
+
type: "boolean",
|
|
1803
|
+
initialValue: false,
|
|
1804
|
+
description: "Enable this to prevent search engines from offering a translated version of this page in search results."
|
|
1805
|
+
}),
|
|
1806
|
+
sanity.defineField({
|
|
1807
|
+
name: "noImageIndex",
|
|
1808
|
+
title: "No Image Index",
|
|
1809
|
+
type: "boolean",
|
|
1810
|
+
initialValue: false,
|
|
1811
|
+
description: "Enable this to prevent images on this page from appearing in image search results."
|
|
988
1812
|
})
|
|
989
1813
|
],
|
|
990
|
-
description: "Select how search engines should index
|
|
1814
|
+
description: "Select how search engines should index, follow links, translate content, and index images on this page."
|
|
991
1815
|
});
|
|
992
1816
|
|
|
993
1817
|
// src/schemas/types/index.ts
|
|
@@ -1003,13 +1827,14 @@ function types(config = {}) {
|
|
|
1003
1827
|
// pass config here
|
|
1004
1828
|
metaAttribute_default,
|
|
1005
1829
|
metaTag_default,
|
|
1006
|
-
robots_default
|
|
1830
|
+
robots_default,
|
|
1831
|
+
hreflang_default
|
|
1007
1832
|
];
|
|
1008
1833
|
}
|
|
1009
1834
|
|
|
1010
1835
|
// src/plugin.ts
|
|
1011
|
-
var resolveDashboardConfig = (healthDashboard, rootApiVersion) => {
|
|
1012
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
|
|
1836
|
+
var resolveDashboardConfig = (healthDashboard, rootApiVersion, rootLicenseKey) => {
|
|
1837
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
1013
1838
|
const cfg = typeof healthDashboard === "object" ? healthDashboard : void 0;
|
|
1014
1839
|
const deprecationWarnings = [];
|
|
1015
1840
|
if ((cfg == null ? void 0 : cfg.apiVersion) !== void 0) {
|
|
@@ -1022,27 +1847,37 @@ var resolveDashboardConfig = (healthDashboard, rootApiVersion) => {
|
|
|
1022
1847
|
'[sanity-plugin-seofields] "healthDashboard.apiVersion" is deprecated. Move it to the root "apiVersion" option instead.'
|
|
1023
1848
|
);
|
|
1024
1849
|
}
|
|
1850
|
+
if ((cfg == null ? void 0 : cfg.licenseKey) !== void 0 && !rootLicenseKey) {
|
|
1851
|
+
deprecationWarnings.push({
|
|
1852
|
+
key: "healthDashboard.licenseKey \u2192 licenseKey",
|
|
1853
|
+
version: "v1.8.0",
|
|
1854
|
+
changelogUrl: "https://github.com/hardik-143/sanity-plugin-seofields/blob/main/CHANGELOG.md"
|
|
1855
|
+
});
|
|
1856
|
+
console.warn(
|
|
1857
|
+
'[sanity-plugin-seofields] "healthDashboard.licenseKey" is deprecated. Move it to the root "licenseKey" option instead.'
|
|
1858
|
+
);
|
|
1859
|
+
}
|
|
1025
1860
|
return {
|
|
1026
1861
|
enabled: healthDashboard !== false,
|
|
1027
|
-
toolTitle: (_b = (_a = cfg == null ? void 0 : cfg.tool) == null ? void 0 : _a.title) != null ? _b : "SEO Health",
|
|
1028
|
-
toolName: (
|
|
1029
|
-
icon: (
|
|
1030
|
-
title: (
|
|
1031
|
-
description: (
|
|
1862
|
+
toolTitle: (_c = (_b = (_a = cfg == null ? void 0 : cfg.tool) == null ? void 0 : _a.title) != null ? _b : cfg == null ? void 0 : cfg.toolTitle) != null ? _c : "SEO Health",
|
|
1863
|
+
toolName: (_e = (_d = cfg == null ? void 0 : cfg.tool) == null ? void 0 : _d.name) != null ? _e : "seo-health-dashboard",
|
|
1864
|
+
icon: (_f = cfg == null ? void 0 : cfg.content) == null ? void 0 : _f.icon,
|
|
1865
|
+
title: (_g = cfg == null ? void 0 : cfg.content) == null ? void 0 : _g.title,
|
|
1866
|
+
description: (_h = cfg == null ? void 0 : cfg.content) == null ? void 0 : _h.description,
|
|
1032
1867
|
showTypeColumn: cfg == null ? void 0 : cfg.showTypeColumn,
|
|
1033
1868
|
showDocumentId: cfg == null ? void 0 : cfg.showDocumentId,
|
|
1034
|
-
queryTypes: (
|
|
1035
|
-
queryRequireSeo: (
|
|
1036
|
-
queryGroq: (
|
|
1037
|
-
apiVersion: (
|
|
1038
|
-
licenseKey: cfg == null ? void 0 : cfg.licenseKey,
|
|
1869
|
+
queryTypes: (_i = cfg == null ? void 0 : cfg.query) == null ? void 0 : _i.types,
|
|
1870
|
+
queryRequireSeo: (_j = cfg == null ? void 0 : cfg.query) == null ? void 0 : _j.requireSeo,
|
|
1871
|
+
queryGroq: (_k = cfg == null ? void 0 : cfg.query) == null ? void 0 : _k.groq,
|
|
1872
|
+
apiVersion: (_l = cfg == null ? void 0 : cfg.apiVersion) != null ? _l : rootApiVersion,
|
|
1873
|
+
licenseKey: rootLicenseKey != null ? rootLicenseKey : cfg == null ? void 0 : cfg.licenseKey,
|
|
1039
1874
|
typeDisplayLabels: cfg == null ? void 0 : cfg.typeDisplayLabels,
|
|
1040
1875
|
typeColumnMode: cfg == null ? void 0 : cfg.typeColumnMode,
|
|
1041
1876
|
titleField: cfg == null ? void 0 : cfg.titleField,
|
|
1042
1877
|
getDocumentBadge: cfg == null ? void 0 : cfg.getDocumentBadge,
|
|
1043
|
-
loadingLicense: (
|
|
1044
|
-
loadingDocuments: (
|
|
1045
|
-
noDocuments: (
|
|
1878
|
+
loadingLicense: (_m = cfg == null ? void 0 : cfg.content) == null ? void 0 : _m.loadingLicense,
|
|
1879
|
+
loadingDocuments: (_n = cfg == null ? void 0 : cfg.content) == null ? void 0 : _n.loadingDocuments,
|
|
1880
|
+
noDocuments: (_o = cfg == null ? void 0 : cfg.content) == null ? void 0 : _o.noDocuments,
|
|
1046
1881
|
previewMode: cfg == null ? void 0 : cfg.previewMode,
|
|
1047
1882
|
structureTool: cfg == null ? void 0 : cfg.structureTool,
|
|
1048
1883
|
exportEnabled: (() => {
|
|
@@ -1057,14 +1892,15 @@ var resolveDashboardConfig = (healthDashboard, rootApiVersion) => {
|
|
|
1057
1892
|
if (typeof exportCfg === "object" && exportCfg.formats) return exportCfg.formats;
|
|
1058
1893
|
return ["csv", "json"];
|
|
1059
1894
|
})(),
|
|
1060
|
-
compactStats: (
|
|
1895
|
+
compactStats: (_p = cfg == null ? void 0 : cfg.compactStats) != null ? _p : false,
|
|
1061
1896
|
deprecationWarnings
|
|
1062
1897
|
};
|
|
1063
1898
|
};
|
|
1064
1899
|
var seofields = sanity.definePlugin((config = {}) => {
|
|
1065
|
-
const
|
|
1066
|
-
const
|
|
1067
|
-
const
|
|
1900
|
+
const cfg = config;
|
|
1901
|
+
const { healthDashboard = true, licenseKey, publishGate } = cfg;
|
|
1902
|
+
const dash = resolveDashboardConfig(healthDashboard, cfg.apiVersion, licenseKey);
|
|
1903
|
+
const LazySeoHealthTool = react.lazy(() => import('./SeoHealthTool-2KKQJLJL.cjs'));
|
|
1068
1904
|
const BoundSeoHealthTool = () => react.createElement(
|
|
1069
1905
|
react.Suspense,
|
|
1070
1906
|
{ fallback: null },
|
|
@@ -1094,12 +1930,23 @@ var seofields = sanity.definePlugin((config = {}) => {
|
|
|
1094
1930
|
_deprecationWarnings: dash.deprecationWarnings
|
|
1095
1931
|
})
|
|
1096
1932
|
);
|
|
1097
|
-
return
|
|
1933
|
+
return chunk254YHUN3_cjs.__spreadValues(chunk254YHUN3_cjs.__spreadValues({
|
|
1098
1934
|
name: "sanity-plugin-seofields",
|
|
1099
1935
|
schema: {
|
|
1100
|
-
types: types(
|
|
1936
|
+
types: types(cfg)
|
|
1101
1937
|
}
|
|
1102
|
-
},
|
|
1938
|
+
}, publishGate && licenseKey && {
|
|
1939
|
+
document: {
|
|
1940
|
+
actions: (prev, context) => {
|
|
1941
|
+
var _a;
|
|
1942
|
+
if (((_a = publishGate.types) == null ? void 0 : _a.length) && !publishGate.types.includes(context.schemaType))
|
|
1943
|
+
return prev;
|
|
1944
|
+
return prev.map(
|
|
1945
|
+
(Action) => Action.action === "publish" ? chunkBNXMFD3T_cjs.createSeoPublishGateAction(Action, chunk254YHUN3_cjs.__spreadProps(chunk254YHUN3_cjs.__spreadValues({}, publishGate), { licenseKey })) : Action
|
|
1946
|
+
);
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
}), dash.enabled && {
|
|
1103
1950
|
tools: [
|
|
1104
1951
|
{
|
|
1105
1952
|
name: dash.toolName,
|
|
@@ -1111,31 +1958,140 @@ var seofields = sanity.definePlugin((config = {}) => {
|
|
|
1111
1958
|
});
|
|
1112
1959
|
});
|
|
1113
1960
|
var plugin_default = seofields;
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1961
|
+
|
|
1962
|
+
// src/utils/scoring.ts
|
|
1963
|
+
var getStatusCategory = (score) => {
|
|
1964
|
+
if (score >= 80) return "excellent";
|
|
1965
|
+
if (score >= 60) return "good";
|
|
1966
|
+
if (score >= 40) return "fair";
|
|
1967
|
+
if (score > 0) return "poor";
|
|
1968
|
+
return "missing";
|
|
1969
|
+
};
|
|
1970
|
+
var scoreMetaTitle = (title) => {
|
|
1971
|
+
const issues = [];
|
|
1972
|
+
let score = 0;
|
|
1973
|
+
if (title && title.length >= 50 && title.length <= 60) {
|
|
1974
|
+
score = 15;
|
|
1975
|
+
} else if (title && title.length > 0) {
|
|
1976
|
+
score = 10;
|
|
1977
|
+
if (title.length < 50) issues.push("Meta title too short (< 50 chars)");
|
|
1978
|
+
if (title.length > 60) issues.push("Meta title too long (> 60 chars)");
|
|
1979
|
+
} else {
|
|
1980
|
+
issues.push("Missing meta title");
|
|
1981
|
+
}
|
|
1982
|
+
return { score, issues };
|
|
1983
|
+
};
|
|
1984
|
+
var scoreMetaDescription = (description) => {
|
|
1985
|
+
const issues = [];
|
|
1986
|
+
let score = 0;
|
|
1987
|
+
if (description && description.length >= 120 && description.length <= 160) {
|
|
1988
|
+
score = 15;
|
|
1989
|
+
} else if (description && description.length > 0) {
|
|
1990
|
+
score = 10;
|
|
1991
|
+
if (description.length < 120) issues.push("Meta description too short (< 120 chars)");
|
|
1992
|
+
if (description.length > 160) issues.push("Meta description too long (> 160 chars)");
|
|
1993
|
+
} else {
|
|
1994
|
+
issues.push("Missing meta description");
|
|
1995
|
+
}
|
|
1996
|
+
return { score, issues };
|
|
1997
|
+
};
|
|
1998
|
+
var scoreOpenGraph = (openGraph2) => {
|
|
1999
|
+
const issues = [];
|
|
2000
|
+
let score = 0;
|
|
2001
|
+
if (openGraph2) {
|
|
2002
|
+
if (openGraph2.title) score += 6;
|
|
2003
|
+
else issues.push("Missing OG title");
|
|
2004
|
+
if (openGraph2.description) score += 6;
|
|
2005
|
+
else issues.push("Missing OG description");
|
|
2006
|
+
if (openGraph2.image) score += 6;
|
|
2007
|
+
else issues.push("Missing OG image");
|
|
2008
|
+
if (openGraph2.type) score += 7;
|
|
2009
|
+
else issues.push("Missing OG type");
|
|
2010
|
+
} else {
|
|
2011
|
+
issues.push("Open Graph not configured");
|
|
2012
|
+
}
|
|
2013
|
+
return { score, issues };
|
|
2014
|
+
};
|
|
2015
|
+
var scoreTwitterCard = (twitter2) => {
|
|
2016
|
+
const issues = [];
|
|
2017
|
+
let score = 0;
|
|
2018
|
+
if (twitter2) {
|
|
2019
|
+
if (twitter2.title) score += 5;
|
|
2020
|
+
else issues.push("Missing Twitter title");
|
|
2021
|
+
if (twitter2.description) score += 5;
|
|
2022
|
+
else issues.push("Missing Twitter description");
|
|
2023
|
+
if (twitter2.image) score += 5;
|
|
2024
|
+
else issues.push("Missing Twitter image");
|
|
2025
|
+
} else {
|
|
2026
|
+
issues.push("Twitter Card not configured");
|
|
2027
|
+
}
|
|
2028
|
+
return { score, issues };
|
|
2029
|
+
};
|
|
2030
|
+
var calculateHealthScore = (doc) => {
|
|
2031
|
+
if (!doc.seo) {
|
|
2032
|
+
return { score: 0, status: "missing", issues: ["SEO fields not configured"] };
|
|
2033
|
+
}
|
|
2034
|
+
const seo = doc.seo;
|
|
2035
|
+
const title = seo.title;
|
|
2036
|
+
const description = seo.description;
|
|
2037
|
+
const keywords = seo.keywords;
|
|
2038
|
+
const robots = seo.robots;
|
|
2039
|
+
const openGraph2 = seo.openGraph;
|
|
2040
|
+
const twitter2 = seo.twitter;
|
|
2041
|
+
let score = 0;
|
|
2042
|
+
const issues = [];
|
|
2043
|
+
const titleResult = scoreMetaTitle(title);
|
|
2044
|
+
score += titleResult.score;
|
|
2045
|
+
issues.push(...titleResult.issues);
|
|
2046
|
+
const descResult = scoreMetaDescription(description);
|
|
2047
|
+
score += descResult.score;
|
|
2048
|
+
issues.push(...descResult.issues);
|
|
2049
|
+
if (seo.metaImage) score += 10;
|
|
2050
|
+
else issues.push("Missing meta image");
|
|
2051
|
+
if (keywords && keywords.length > 0) score += 10;
|
|
2052
|
+
else issues.push("No keywords defined");
|
|
2053
|
+
if (robots && !robots.noIndex) score += 5;
|
|
2054
|
+
else if (!robots) score += 5;
|
|
2055
|
+
const ogResult = scoreOpenGraph(openGraph2);
|
|
2056
|
+
score += ogResult.score;
|
|
2057
|
+
issues.push(...ogResult.issues);
|
|
2058
|
+
const twResult = scoreTwitterCard(twitter2);
|
|
2059
|
+
score += twResult.score;
|
|
2060
|
+
issues.push(...twResult.issues);
|
|
2061
|
+
const hasMetaImage = !!seo.metaImage;
|
|
2062
|
+
const hasOgImage = !!(openGraph2 && openGraph2.image);
|
|
2063
|
+
const hasTwitterImage = !!(twitter2 && twitter2.image);
|
|
2064
|
+
if (hasMetaImage && hasOgImage && hasTwitterImage) {
|
|
2065
|
+
score += 5;
|
|
2066
|
+
} else {
|
|
2067
|
+
const missingImages = [];
|
|
2068
|
+
if (!hasMetaImage) missingImages.push("meta image");
|
|
2069
|
+
if (!hasOgImage) missingImages.push("OG image");
|
|
2070
|
+
if (!hasTwitterImage) missingImages.push("Twitter image");
|
|
2071
|
+
issues.push(`Missing images for full score: ${missingImages.join(", ")}`);
|
|
2072
|
+
}
|
|
2073
|
+
const status = getStatusCategory(score);
|
|
2074
|
+
return { score, status, issues };
|
|
2075
|
+
};
|
|
1132
2076
|
|
|
1133
2077
|
// src/index.ts
|
|
1134
2078
|
var src_default = plugin_default;
|
|
1135
2079
|
|
|
2080
|
+
Object.defineProperty(exports, "SchemaOrgDocumentJsonLdPreview", {
|
|
2081
|
+
enumerable: true,
|
|
2082
|
+
get: function () { return chunkB5IVI5LP_cjs.SchemaOrgJsonLdPreview; }
|
|
2083
|
+
});
|
|
2084
|
+
Object.defineProperty(exports, "SchemaOrgJsonLdPreview", {
|
|
2085
|
+
enumerable: true,
|
|
2086
|
+
get: function () { return chunkB5IVI5LP_cjs.SchemaOrgJsonLdPreview; }
|
|
2087
|
+
});
|
|
2088
|
+
Object.defineProperty(exports, "createSeoHealthPane", {
|
|
2089
|
+
enumerable: true,
|
|
2090
|
+
get: function () { return chunkBNXMFD3T_cjs.createSeoHealthPane; }
|
|
2091
|
+
});
|
|
1136
2092
|
exports.allSchemas = types;
|
|
1137
2093
|
exports.baseMetaSchema = baseMeta;
|
|
1138
|
-
exports.
|
|
2094
|
+
exports.calculateHealthScore = calculateHealthScore;
|
|
1139
2095
|
exports.default = src_default;
|
|
1140
2096
|
exports.metaAttributeSchema = metaAttribute_default;
|
|
1141
2097
|
exports.metaTagSchema = metaTag_default;
|