@consilioweb/payload-seo-analyzer 1.9.0 → 1.11.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 +46 -0
- package/dist/client.cjs +902 -85
- package/dist/client.js +902 -85
- package/dist/index.cjs +1431 -225
- package/dist/index.d.cts +114 -3
- package/dist/index.d.ts +114 -3
- package/dist/index.js +1435 -235
- package/package.json +1 -1
package/dist/client.cjs
CHANGED
|
@@ -1065,6 +1065,9 @@ var fr = {
|
|
|
1065
1065
|
pagesAnalyzed: "pages analys\xE9es",
|
|
1066
1066
|
markCornerstone: "Marquer pilier",
|
|
1067
1067
|
unmarkCornerstone: "D\xE9marquer pilier",
|
|
1068
|
+
bulkOptimizeMeta: "Optimiser m\xE9ta (IA)",
|
|
1069
|
+
bulkOptimizing: "Optimisation\u2026",
|
|
1070
|
+
bulkConfirm: "Confirmer ?",
|
|
1068
1071
|
searchPlaceholder: "Rechercher (titre, slug, keyword)...",
|
|
1069
1072
|
allCollections: "Toutes les collections",
|
|
1070
1073
|
allScores: "Tous les scores",
|
|
@@ -1657,6 +1660,9 @@ var en = {
|
|
|
1657
1660
|
pagesAnalyzed: "pages analyzed",
|
|
1658
1661
|
markCornerstone: "Mark as cornerstone",
|
|
1659
1662
|
unmarkCornerstone: "Unmark cornerstone",
|
|
1663
|
+
bulkOptimizeMeta: "Optimize meta (AI)",
|
|
1664
|
+
bulkOptimizing: "Optimizing\u2026",
|
|
1665
|
+
bulkConfirm: "Confirm?",
|
|
1660
1666
|
searchPlaceholder: "Search (title, slug, keyword)...",
|
|
1661
1667
|
allCollections: "All collections",
|
|
1662
1668
|
allScores: "All scores",
|
|
@@ -9201,8 +9207,11 @@ function BulkActionBar({
|
|
|
9201
9207
|
onExportCsv,
|
|
9202
9208
|
onMarkCornerstone,
|
|
9203
9209
|
onUnmarkCornerstone,
|
|
9210
|
+
onOptimizeMeta,
|
|
9211
|
+
optimizing,
|
|
9204
9212
|
t
|
|
9205
9213
|
}) {
|
|
9214
|
+
const [confirmOptimize, setConfirmOptimize] = React4.useState(false);
|
|
9206
9215
|
if (count === 0) return null;
|
|
9207
9216
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9208
9217
|
"div",
|
|
@@ -9248,6 +9257,24 @@ function BulkActionBar({
|
|
|
9248
9257
|
children: t.common.exportCsv
|
|
9249
9258
|
}
|
|
9250
9259
|
),
|
|
9260
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9261
|
+
"button",
|
|
9262
|
+
{
|
|
9263
|
+
onClick: () => {
|
|
9264
|
+
if (optimizing) return;
|
|
9265
|
+
if (confirmOptimize) {
|
|
9266
|
+
setConfirmOptimize(false);
|
|
9267
|
+
onOptimizeMeta();
|
|
9268
|
+
} else {
|
|
9269
|
+
setConfirmOptimize(true);
|
|
9270
|
+
setTimeout(() => setConfirmOptimize(false), 4e3);
|
|
9271
|
+
}
|
|
9272
|
+
},
|
|
9273
|
+
disabled: optimizing,
|
|
9274
|
+
style: { ...btnBase, backgroundColor: "#7c3aed", color: "#fff", opacity: optimizing ? 0.6 : 1 },
|
|
9275
|
+
children: optimizing ? t.seoView.bulkOptimizing : confirmOptimize ? t.seoView.bulkConfirm : `\u2728 ${t.seoView.bulkOptimizeMeta}`
|
|
9276
|
+
}
|
|
9277
|
+
),
|
|
9251
9278
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9252
9279
|
"button",
|
|
9253
9280
|
{
|
|
@@ -9288,6 +9315,7 @@ function SeoView() {
|
|
|
9288
9315
|
const [expandedId, setExpandedId] = React4.useState(null);
|
|
9289
9316
|
const [saving, setSaving] = React4.useState(false);
|
|
9290
9317
|
const [saveError, setSaveError] = React4.useState(null);
|
|
9318
|
+
const [bulkOptimizing, setBulkOptimizing] = React4.useState(false);
|
|
9291
9319
|
const PAGE_SIZE = 50;
|
|
9292
9320
|
const fetchAudit = React4.useCallback(async (forceRefresh = false) => {
|
|
9293
9321
|
setLoading(true);
|
|
@@ -9508,6 +9536,45 @@ function SeoView() {
|
|
|
9508
9536
|
},
|
|
9509
9537
|
[selectedIds, fetchAudit]
|
|
9510
9538
|
);
|
|
9539
|
+
const handleBulkOptimizeMeta = React4.useCallback(async () => {
|
|
9540
|
+
const keys = Array.from(selectedIds);
|
|
9541
|
+
if (keys.length === 0) return;
|
|
9542
|
+
setBulkOptimizing(true);
|
|
9543
|
+
for (const key of keys) {
|
|
9544
|
+
const [collection, id] = key.split("::");
|
|
9545
|
+
if (!collection || !id || collection.startsWith("global:")) continue;
|
|
9546
|
+
try {
|
|
9547
|
+
const res = await fetch("/api/seo-plugin/ai-optimize", {
|
|
9548
|
+
method: "POST",
|
|
9549
|
+
headers: { "Content-Type": "application/json" },
|
|
9550
|
+
credentials: "include",
|
|
9551
|
+
body: JSON.stringify({ collection, id })
|
|
9552
|
+
});
|
|
9553
|
+
if (!res.ok) continue;
|
|
9554
|
+
const data = await res.json();
|
|
9555
|
+
const sug = data.suggestions || {};
|
|
9556
|
+
const patch = {};
|
|
9557
|
+
if (sug.metaTitle || sug.metaDescription) {
|
|
9558
|
+
patch.meta = { title: sug.metaTitle, description: sug.metaDescription };
|
|
9559
|
+
}
|
|
9560
|
+
if (sug.focusKeyword && sug.focusKeyword !== data.current?.focusKeyword) {
|
|
9561
|
+
patch.focusKeyword = sug.focusKeyword;
|
|
9562
|
+
}
|
|
9563
|
+
if (Object.keys(patch).length > 0) {
|
|
9564
|
+
await fetch(`/api/${collection}/${id}`, {
|
|
9565
|
+
method: "PATCH",
|
|
9566
|
+
headers: { "Content-Type": "application/json" },
|
|
9567
|
+
credentials: "include",
|
|
9568
|
+
body: JSON.stringify(patch)
|
|
9569
|
+
});
|
|
9570
|
+
}
|
|
9571
|
+
} catch {
|
|
9572
|
+
}
|
|
9573
|
+
}
|
|
9574
|
+
setBulkOptimizing(false);
|
|
9575
|
+
setSelectedIds(/* @__PURE__ */ new Set());
|
|
9576
|
+
fetchAudit();
|
|
9577
|
+
}, [selectedIds, fetchAudit]);
|
|
9511
9578
|
const handleInlineSave = React4.useCallback(
|
|
9512
9579
|
async (item, metaTitle, metaDescription) => {
|
|
9513
9580
|
setSaving(true);
|
|
@@ -10256,6 +10323,8 @@ function SeoView() {
|
|
|
10256
10323
|
onExportCsv: handleBulkExportCsv,
|
|
10257
10324
|
onMarkCornerstone: () => handleBulkCornerstone(true),
|
|
10258
10325
|
onUnmarkCornerstone: () => handleBulkCornerstone(false),
|
|
10326
|
+
onOptimizeMeta: handleBulkOptimizeMeta,
|
|
10327
|
+
optimizing: bulkOptimizing,
|
|
10259
10328
|
t
|
|
10260
10329
|
}
|
|
10261
10330
|
)
|
|
@@ -15910,7 +15979,7 @@ function getSchemaTypes(t) {
|
|
|
15910
15979
|
}
|
|
15911
15980
|
};
|
|
15912
15981
|
}
|
|
15913
|
-
function
|
|
15982
|
+
function buildJsonLd2(type, values) {
|
|
15914
15983
|
switch (type) {
|
|
15915
15984
|
case "LocalBusiness": {
|
|
15916
15985
|
const result = {
|
|
@@ -16191,7 +16260,7 @@ function SchemaBuilderView() {
|
|
|
16191
16260
|
[arrayName]: (prev[arrayName] || []).filter((_, i) => i !== index)
|
|
16192
16261
|
}));
|
|
16193
16262
|
}, []);
|
|
16194
|
-
const jsonLd = React4.useMemo(() =>
|
|
16263
|
+
const jsonLd = React4.useMemo(() => buildJsonLd2(selectedType, values), [selectedType, values]);
|
|
16195
16264
|
const jsonString = React4.useMemo(() => JSON.stringify(jsonLd, null, 2), [jsonLd]);
|
|
16196
16265
|
const scriptTag = React4.useMemo(
|
|
16197
16266
|
() => `<script type="application/ld+json">
|
|
@@ -16968,6 +17037,573 @@ function GscPanel({ locale }) {
|
|
|
16968
17037
|
] })
|
|
16969
17038
|
] });
|
|
16970
17039
|
}
|
|
17040
|
+
var C6 = {
|
|
17041
|
+
text: "var(--theme-text, #1a1a1a)",
|
|
17042
|
+
sub: "var(--theme-elevation-600, #6b7280)",
|
|
17043
|
+
card: "var(--theme-elevation-50, #f9fafb)",
|
|
17044
|
+
border: "var(--theme-elevation-200, #e5e7eb)",
|
|
17045
|
+
green: "#22c55e",
|
|
17046
|
+
red: "#ef4444",
|
|
17047
|
+
blue: "#3b82f6"
|
|
17048
|
+
};
|
|
17049
|
+
var S3 = {
|
|
17050
|
+
fr: {
|
|
17051
|
+
title: "Suivi de positions (rank tracking)",
|
|
17052
|
+
subtitle: "Historique quotidien des positions Google (via Search Console) et mouvements dans le temps.",
|
|
17053
|
+
needGsc: "Connectez Google Search Console ci-dessus pour activer le suivi de positions.",
|
|
17054
|
+
snapshot: "Relever maintenant",
|
|
17055
|
+
snapshotting: "Relev\xE9 en cours\u2026",
|
|
17056
|
+
noData: "Pas encore de donn\xE9es. Le relev\xE9 tourne automatiquement chaque jour ; cliquez \xAB Relever maintenant \xBB pour d\xE9marrer.",
|
|
17057
|
+
lastSnapshot: "Dernier relev\xE9",
|
|
17058
|
+
query: "Requ\xEAte",
|
|
17059
|
+
position: "Position",
|
|
17060
|
+
change: "\xC9volution",
|
|
17061
|
+
clicks: "Clics",
|
|
17062
|
+
impressions: "Impr.",
|
|
17063
|
+
stable: "stable",
|
|
17064
|
+
newQ: "nouveau",
|
|
17065
|
+
countLabel: "requ\xEAtes suivies"
|
|
17066
|
+
},
|
|
17067
|
+
en: {
|
|
17068
|
+
title: "Rank tracking",
|
|
17069
|
+
subtitle: "Daily Google position history (via Search Console) and movement over time.",
|
|
17070
|
+
needGsc: "Connect Google Search Console above to enable rank tracking.",
|
|
17071
|
+
snapshot: "Snapshot now",
|
|
17072
|
+
snapshotting: "Snapshotting\u2026",
|
|
17073
|
+
noData: 'No data yet. The snapshot runs automatically every day; click "Snapshot now" to start.',
|
|
17074
|
+
lastSnapshot: "Last snapshot",
|
|
17075
|
+
query: "Query",
|
|
17076
|
+
position: "Position",
|
|
17077
|
+
change: "Change",
|
|
17078
|
+
clicks: "Clicks",
|
|
17079
|
+
impressions: "Impr.",
|
|
17080
|
+
stable: "stable",
|
|
17081
|
+
newQ: "new",
|
|
17082
|
+
countLabel: "tracked queries"
|
|
17083
|
+
}
|
|
17084
|
+
};
|
|
17085
|
+
function RankTrackingPanel({ locale }) {
|
|
17086
|
+
const s = S3[locale] ?? S3.fr;
|
|
17087
|
+
const [movers, setMovers] = React4.useState(null);
|
|
17088
|
+
const [lastSnapshot, setLastSnapshot] = React4.useState(null);
|
|
17089
|
+
const [loading, setLoading] = React4.useState(true);
|
|
17090
|
+
const [busy, setBusy] = React4.useState(false);
|
|
17091
|
+
const [error, setError] = React4.useState(null);
|
|
17092
|
+
const [notConnected, setNotConnected] = React4.useState(false);
|
|
17093
|
+
const load = React4.useCallback(async () => {
|
|
17094
|
+
setLoading(true);
|
|
17095
|
+
setError(null);
|
|
17096
|
+
try {
|
|
17097
|
+
const res = await fetch("/api/seo-plugin/rank-history", { credentials: "include", cache: "no-store" });
|
|
17098
|
+
if (res.status === 403 || res.status === 409) {
|
|
17099
|
+
setNotConnected(true);
|
|
17100
|
+
setMovers(null);
|
|
17101
|
+
return;
|
|
17102
|
+
}
|
|
17103
|
+
const json = await res.json();
|
|
17104
|
+
if (!res.ok) {
|
|
17105
|
+
setError(json.error || `Error ${res.status}`);
|
|
17106
|
+
return;
|
|
17107
|
+
}
|
|
17108
|
+
setMovers(json.movers || []);
|
|
17109
|
+
setLastSnapshot(json.lastSnapshot || null);
|
|
17110
|
+
} catch (e) {
|
|
17111
|
+
setError(e instanceof Error ? e.message : "Network error");
|
|
17112
|
+
} finally {
|
|
17113
|
+
setLoading(false);
|
|
17114
|
+
}
|
|
17115
|
+
}, []);
|
|
17116
|
+
React4.useEffect(() => {
|
|
17117
|
+
void load();
|
|
17118
|
+
}, [load]);
|
|
17119
|
+
const snapshotNow = async () => {
|
|
17120
|
+
setBusy(true);
|
|
17121
|
+
setError(null);
|
|
17122
|
+
try {
|
|
17123
|
+
const res = await fetch("/api/seo-plugin/rank-snapshot", { method: "POST", credentials: "include" });
|
|
17124
|
+
const json = await res.json();
|
|
17125
|
+
if (res.status === 409) {
|
|
17126
|
+
setNotConnected(true);
|
|
17127
|
+
return;
|
|
17128
|
+
}
|
|
17129
|
+
if (!res.ok) {
|
|
17130
|
+
setError(json.error || json.reason || `Error ${res.status}`);
|
|
17131
|
+
return;
|
|
17132
|
+
}
|
|
17133
|
+
await load();
|
|
17134
|
+
} catch (e) {
|
|
17135
|
+
setError(e instanceof Error ? e.message : "Network error");
|
|
17136
|
+
} finally {
|
|
17137
|
+
setBusy(false);
|
|
17138
|
+
}
|
|
17139
|
+
};
|
|
17140
|
+
const card = {
|
|
17141
|
+
padding: 16,
|
|
17142
|
+
borderRadius: 12,
|
|
17143
|
+
border: `1px solid ${C6.border}`,
|
|
17144
|
+
backgroundColor: C6.card,
|
|
17145
|
+
marginBottom: 20
|
|
17146
|
+
};
|
|
17147
|
+
const btn = {
|
|
17148
|
+
padding: "8px 12px",
|
|
17149
|
+
borderRadius: 8,
|
|
17150
|
+
border: `1px solid ${C6.blue}`,
|
|
17151
|
+
backgroundColor: C6.blue,
|
|
17152
|
+
color: "#fff",
|
|
17153
|
+
fontSize: 12,
|
|
17154
|
+
fontWeight: 700,
|
|
17155
|
+
cursor: busy ? "wait" : "pointer",
|
|
17156
|
+
opacity: busy ? 0.6 : 1
|
|
17157
|
+
};
|
|
17158
|
+
const renderDelta = (m) => {
|
|
17159
|
+
if (m.previousPosition === null) {
|
|
17160
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C6.sub, fontSize: 11 }, children: s.newQ });
|
|
17161
|
+
}
|
|
17162
|
+
if (Math.abs(m.delta) < 0.1) {
|
|
17163
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: C6.sub, fontSize: 11 }, children: [
|
|
17164
|
+
"\u2014 ",
|
|
17165
|
+
s.stable
|
|
17166
|
+
] });
|
|
17167
|
+
}
|
|
17168
|
+
const up = m.delta > 0;
|
|
17169
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: up ? C6.green : C6.red, fontWeight: 700, fontSize: 12 }, children: [
|
|
17170
|
+
up ? "\u25B2" : "\u25BC",
|
|
17171
|
+
" ",
|
|
17172
|
+
Math.abs(m.delta).toFixed(1)
|
|
17173
|
+
] });
|
|
17174
|
+
};
|
|
17175
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: card, children: [
|
|
17176
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, flexWrap: "wrap" }, children: [
|
|
17177
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
17178
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C6.text }, children: s.title }),
|
|
17179
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C6.sub, marginTop: 2 }, children: s.subtitle })
|
|
17180
|
+
] }),
|
|
17181
|
+
!notConnected && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: snapshotNow, disabled: busy, style: btn, children: busy ? s.snapshotting : s.snapshot })
|
|
17182
|
+
] }),
|
|
17183
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C6.red, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: error }),
|
|
17184
|
+
notConnected && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C6.sub }, children: s.needGsc }),
|
|
17185
|
+
!notConnected && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 12 }, children: [
|
|
17186
|
+
lastSnapshot && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 11, color: C6.sub, marginBottom: 8 }, children: [
|
|
17187
|
+
s.lastSnapshot,
|
|
17188
|
+
": ",
|
|
17189
|
+
new Date(lastSnapshot).toLocaleString(locale),
|
|
17190
|
+
movers ? ` \xB7 ${movers.length} ${s.countLabel}` : ""
|
|
17191
|
+
] }),
|
|
17192
|
+
loading && !movers && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C6.sub }, children: "\u2026" }),
|
|
17193
|
+
movers && movers.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C6.sub }, children: s.noData }),
|
|
17194
|
+
movers && movers.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsxs("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: 12 }, children: [
|
|
17195
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { style: { textAlign: "left", color: C6.sub }, children: [
|
|
17196
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px" }, children: s.query }),
|
|
17197
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px", textAlign: "right" }, children: s.position }),
|
|
17198
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px", textAlign: "right" }, children: s.change }),
|
|
17199
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px", textAlign: "right" }, children: s.clicks }),
|
|
17200
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { style: { padding: "6px 8px", textAlign: "right" }, children: s.impressions })
|
|
17201
|
+
] }) }),
|
|
17202
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: movers.slice(0, 100).map((m, i) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { style: { borderTop: `1px solid ${C6.border}`, color: C6.text }, children: [
|
|
17203
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", maxWidth: 320, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: m.query }),
|
|
17204
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", textAlign: "right", fontWeight: 700 }, children: m.position.toFixed(1) }),
|
|
17205
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", textAlign: "right" }, children: renderDelta(m) }),
|
|
17206
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", textAlign: "right" }, children: m.clicks }),
|
|
17207
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "6px 8px", textAlign: "right" }, children: m.impressions })
|
|
17208
|
+
] }, i)) })
|
|
17209
|
+
] }) })
|
|
17210
|
+
] })
|
|
17211
|
+
] });
|
|
17212
|
+
}
|
|
17213
|
+
var C7 = {
|
|
17214
|
+
text: "var(--theme-text, #1a1a1a)",
|
|
17215
|
+
sub: "var(--theme-elevation-600, #6b7280)",
|
|
17216
|
+
card: "var(--theme-elevation-50, #f9fafb)",
|
|
17217
|
+
border: "var(--theme-elevation-200, #e5e7eb)",
|
|
17218
|
+
green: "#22c55e",
|
|
17219
|
+
red: "#ef4444",
|
|
17220
|
+
amber: "#f59e0b",
|
|
17221
|
+
blue: "#3b82f6"
|
|
17222
|
+
};
|
|
17223
|
+
var S4 = {
|
|
17224
|
+
fr: {
|
|
17225
|
+
title: "Monitoring & alertes",
|
|
17226
|
+
subtitle: "Digest p\xE9riodique : r\xE9gressions de score, nouveaux 404, chutes de position (webhook / email).",
|
|
17227
|
+
notConfigured: "Aucun canal configur\xE9. D\xE9finissez SEO_ALERT_WEBHOOK_URL et/ou SEO_ALERT_EMAIL c\xF4t\xE9 serveur, puis activez features.alerts.",
|
|
17228
|
+
webhook: "Webhook",
|
|
17229
|
+
email: "Email",
|
|
17230
|
+
configured: "configur\xE9",
|
|
17231
|
+
missing: "absent",
|
|
17232
|
+
preview: "Aper\xE7u",
|
|
17233
|
+
sendNow: "Envoyer maintenant",
|
|
17234
|
+
sending: "Envoi\u2026",
|
|
17235
|
+
loading: "Chargement\u2026",
|
|
17236
|
+
noIssues: "Aucun probl\xE8me d\xE9tect\xE9 sur la p\xE9riode. \u{1F389}",
|
|
17237
|
+
scoreReg: "R\xE9gressions de score",
|
|
17238
|
+
notFound: "Nouveaux 404",
|
|
17239
|
+
rankDrops: "Chutes de position",
|
|
17240
|
+
sent: "Digest envoy\xE9",
|
|
17241
|
+
nothingToSend: "Rien \xE0 envoyer (aucun probl\xE8me).",
|
|
17242
|
+
issues: "probl\xE8me(s)"
|
|
17243
|
+
},
|
|
17244
|
+
en: {
|
|
17245
|
+
title: "Monitoring & alerts",
|
|
17246
|
+
subtitle: "Periodic digest: score regressions, new 404s, ranking drops (webhook / email).",
|
|
17247
|
+
notConfigured: "No channel configured. Set SEO_ALERT_WEBHOOK_URL and/or SEO_ALERT_EMAIL on the server, then enable features.alerts.",
|
|
17248
|
+
webhook: "Webhook",
|
|
17249
|
+
email: "Email",
|
|
17250
|
+
configured: "configured",
|
|
17251
|
+
missing: "missing",
|
|
17252
|
+
preview: "Preview",
|
|
17253
|
+
sendNow: "Send now",
|
|
17254
|
+
sending: "Sending\u2026",
|
|
17255
|
+
loading: "Loading\u2026",
|
|
17256
|
+
noIssues: "No issues for the period. \u{1F389}",
|
|
17257
|
+
scoreReg: "Score regressions",
|
|
17258
|
+
notFound: "New 404s",
|
|
17259
|
+
rankDrops: "Ranking drops",
|
|
17260
|
+
sent: "Digest sent",
|
|
17261
|
+
nothingToSend: "Nothing to send (no issues).",
|
|
17262
|
+
issues: "issue(s)"
|
|
17263
|
+
}
|
|
17264
|
+
};
|
|
17265
|
+
function AlertsPanel({ locale }) {
|
|
17266
|
+
const s = S4[locale] ?? S4.fr;
|
|
17267
|
+
const [digest, setDigest] = React4.useState(null);
|
|
17268
|
+
const [config, setConfig] = React4.useState(null);
|
|
17269
|
+
const [loading, setLoading] = React4.useState(true);
|
|
17270
|
+
const [busy, setBusy] = React4.useState(false);
|
|
17271
|
+
const [error, setError] = React4.useState(null);
|
|
17272
|
+
const [notice, setNotice] = React4.useState(null);
|
|
17273
|
+
const load = React4.useCallback(async () => {
|
|
17274
|
+
setLoading(true);
|
|
17275
|
+
setError(null);
|
|
17276
|
+
try {
|
|
17277
|
+
const res = await fetch("/api/seo-plugin/alerts-digest", { credentials: "include", cache: "no-store" });
|
|
17278
|
+
if (res.status === 404 || res.status === 403) {
|
|
17279
|
+
setConfig({ webhookConfigured: false, emailConfigured: false, scoreDrop: 0, positionDrop: 0, windowHours: 0 });
|
|
17280
|
+
setDigest(null);
|
|
17281
|
+
return;
|
|
17282
|
+
}
|
|
17283
|
+
const json = await res.json();
|
|
17284
|
+
if (!res.ok) {
|
|
17285
|
+
setError(json.error || `Error ${res.status}`);
|
|
17286
|
+
return;
|
|
17287
|
+
}
|
|
17288
|
+
setDigest(json.digest);
|
|
17289
|
+
setConfig(json.config);
|
|
17290
|
+
} catch (e) {
|
|
17291
|
+
setError(e instanceof Error ? e.message : "Network error");
|
|
17292
|
+
} finally {
|
|
17293
|
+
setLoading(false);
|
|
17294
|
+
}
|
|
17295
|
+
}, []);
|
|
17296
|
+
React4.useEffect(() => {
|
|
17297
|
+
void load();
|
|
17298
|
+
}, [load]);
|
|
17299
|
+
const sendNow = async () => {
|
|
17300
|
+
setBusy(true);
|
|
17301
|
+
setError(null);
|
|
17302
|
+
setNotice(null);
|
|
17303
|
+
try {
|
|
17304
|
+
const res = await fetch("/api/seo-plugin/alerts-run", { method: "POST", credentials: "include" });
|
|
17305
|
+
const json = await res.json();
|
|
17306
|
+
if (!res.ok) {
|
|
17307
|
+
setError(json.error || `Error ${res.status}`);
|
|
17308
|
+
return;
|
|
17309
|
+
}
|
|
17310
|
+
setNotice(json.delivery?.sent ? s.sent : s.nothingToSend);
|
|
17311
|
+
if (json.digest) setDigest(json.digest);
|
|
17312
|
+
} catch (e) {
|
|
17313
|
+
setError(e instanceof Error ? e.message : "Network error");
|
|
17314
|
+
} finally {
|
|
17315
|
+
setBusy(false);
|
|
17316
|
+
}
|
|
17317
|
+
};
|
|
17318
|
+
const card = {
|
|
17319
|
+
padding: 16,
|
|
17320
|
+
borderRadius: 12,
|
|
17321
|
+
border: `1px solid ${C7.border}`,
|
|
17322
|
+
backgroundColor: C7.card,
|
|
17323
|
+
marginBottom: 20
|
|
17324
|
+
};
|
|
17325
|
+
const btn = {
|
|
17326
|
+
padding: "8px 12px",
|
|
17327
|
+
borderRadius: 8,
|
|
17328
|
+
border: `1px solid ${C7.blue}`,
|
|
17329
|
+
backgroundColor: C7.blue,
|
|
17330
|
+
color: "#fff",
|
|
17331
|
+
fontSize: 12,
|
|
17332
|
+
fontWeight: 700,
|
|
17333
|
+
cursor: busy ? "wait" : "pointer",
|
|
17334
|
+
opacity: busy ? 0.6 : 1
|
|
17335
|
+
};
|
|
17336
|
+
const chip = (ok, label) => ({
|
|
17337
|
+
fontSize: 11,
|
|
17338
|
+
fontWeight: 700,
|
|
17339
|
+
padding: "3px 8px",
|
|
17340
|
+
borderRadius: 999,
|
|
17341
|
+
color: "#fff",
|
|
17342
|
+
backgroundColor: ok ? C7.green : C7.sub,
|
|
17343
|
+
marginRight: 6
|
|
17344
|
+
});
|
|
17345
|
+
const hasChannel = config && (config.webhookConfigured || config.emailConfigured);
|
|
17346
|
+
const list = (title, rows) => rows.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 10 }, children: [
|
|
17347
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, fontWeight: 700, color: C7.text, marginBottom: 4 }, children: [
|
|
17348
|
+
title,
|
|
17349
|
+
" ",
|
|
17350
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: C7.amber }, children: [
|
|
17351
|
+
"(",
|
|
17352
|
+
rows.length,
|
|
17353
|
+
")"
|
|
17354
|
+
] })
|
|
17355
|
+
] }),
|
|
17356
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 12, color: C7.sub, lineHeight: 1.6 }, children: rows.slice(0, 8).map((r, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: r }, i)) })
|
|
17357
|
+
] }) : null;
|
|
17358
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: card, children: [
|
|
17359
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, flexWrap: "wrap" }, children: [
|
|
17360
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
17361
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C7.text }, children: s.title }),
|
|
17362
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C7.sub, marginTop: 2 }, children: s.subtitle })
|
|
17363
|
+
] }),
|
|
17364
|
+
hasChannel && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: sendNow, disabled: busy, style: btn, children: busy ? s.sending : s.sendNow })
|
|
17365
|
+
] }),
|
|
17366
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C7.red, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: error }),
|
|
17367
|
+
notice && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C7.green, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: notice }),
|
|
17368
|
+
config && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 12 }, children: [
|
|
17369
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: chip(config.webhookConfigured, s.webhook), children: [
|
|
17370
|
+
s.webhook,
|
|
17371
|
+
": ",
|
|
17372
|
+
config.webhookConfigured ? s.configured : s.missing
|
|
17373
|
+
] }),
|
|
17374
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: chip(config.emailConfigured, s.email), children: [
|
|
17375
|
+
s.email,
|
|
17376
|
+
": ",
|
|
17377
|
+
config.emailConfigured ? s.configured : s.missing
|
|
17378
|
+
] })
|
|
17379
|
+
] }),
|
|
17380
|
+
!loading && !hasChannel && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C7.sub }, children: s.notConfigured }),
|
|
17381
|
+
loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C7.sub }, children: s.loading }),
|
|
17382
|
+
digest && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 8 }, children: [
|
|
17383
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: C7.sub, marginTop: 6 }, children: [
|
|
17384
|
+
digest.totalIssues,
|
|
17385
|
+
" ",
|
|
17386
|
+
s.issues
|
|
17387
|
+
] }),
|
|
17388
|
+
digest.totalIssues === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 8, fontSize: 13, color: C7.sub }, children: s.noIssues }),
|
|
17389
|
+
list(
|
|
17390
|
+
s.scoreReg,
|
|
17391
|
+
digest.scoreRegressions.map((r) => `${r.collection}/${r.documentId} \u2014 ${r.from} \u2192 ${r.to} (\u2212${r.drop})`)
|
|
17392
|
+
),
|
|
17393
|
+
list(s.notFound, digest.newNotFound.map((n) => `${n.url} \u2014 ${n.count}\xD7`)),
|
|
17394
|
+
list(s.rankDrops, digest.rankDrops.map((d) => `\u201C${d.query}\u201D \u2014 #${d.from} \u2192 #${d.to} (\u25BC${d.drop})`))
|
|
17395
|
+
] })
|
|
17396
|
+
] });
|
|
17397
|
+
}
|
|
17398
|
+
var C8 = {
|
|
17399
|
+
text: "var(--theme-text, #1a1a1a)",
|
|
17400
|
+
sub: "var(--theme-elevation-600, #6b7280)",
|
|
17401
|
+
card: "var(--theme-elevation-50, #f9fafb)",
|
|
17402
|
+
bg: "var(--theme-elevation-0, #fff)",
|
|
17403
|
+
border: "var(--theme-elevation-200, #e5e7eb)",
|
|
17404
|
+
green: "#22c55e",
|
|
17405
|
+
red: "#ef4444",
|
|
17406
|
+
violet: "#7c3aed"
|
|
17407
|
+
};
|
|
17408
|
+
var S5 = {
|
|
17409
|
+
fr: {
|
|
17410
|
+
title: "Alt-text IA des images",
|
|
17411
|
+
subtitle: "G\xE9n\xE8re l'attribut alt des images qui n'en ont pas (Claude vision), pour l'accessibilit\xE9 et le SEO.",
|
|
17412
|
+
none: "Toutes les images ont un alt. \u{1F389}",
|
|
17413
|
+
forbidden: "R\xE9serv\xE9 aux administrateurs.",
|
|
17414
|
+
disabled: "Fonction IA d\xE9sactiv\xE9e (features.aiFeatures).",
|
|
17415
|
+
missing: "image(s) sans alt",
|
|
17416
|
+
generate: "G\xE9n\xE9rer",
|
|
17417
|
+
generating: "\u2026",
|
|
17418
|
+
apply: "Appliquer",
|
|
17419
|
+
applied: "Appliqu\xE9 \u2713",
|
|
17420
|
+
noKey: "Cl\xE9 API Claude requise (ANTHROPIC_API_KEY).",
|
|
17421
|
+
loading: "Chargement\u2026",
|
|
17422
|
+
refresh: "Rafra\xEEchir"
|
|
17423
|
+
},
|
|
17424
|
+
en: {
|
|
17425
|
+
title: "AI image alt-text",
|
|
17426
|
+
subtitle: "Generate alt text for images that lack one (Claude vision), for accessibility and SEO.",
|
|
17427
|
+
none: "All images have alt text. \u{1F389}",
|
|
17428
|
+
forbidden: "Admins only.",
|
|
17429
|
+
disabled: "AI feature disabled (features.aiFeatures).",
|
|
17430
|
+
missing: "image(s) without alt",
|
|
17431
|
+
generate: "Generate",
|
|
17432
|
+
generating: "\u2026",
|
|
17433
|
+
apply: "Apply",
|
|
17434
|
+
applied: "Applied \u2713",
|
|
17435
|
+
noKey: "Claude API key required (ANTHROPIC_API_KEY).",
|
|
17436
|
+
loading: "Loading\u2026",
|
|
17437
|
+
refresh: "Refresh"
|
|
17438
|
+
}
|
|
17439
|
+
};
|
|
17440
|
+
function AltTextPanel({ locale }) {
|
|
17441
|
+
const s = S5[locale] ?? S5.fr;
|
|
17442
|
+
const [items, setItems] = React4.useState(null);
|
|
17443
|
+
const [collection, setCollection] = React4.useState("media");
|
|
17444
|
+
const [missingCount, setMissingCount] = React4.useState(0);
|
|
17445
|
+
const [loading, setLoading] = React4.useState(true);
|
|
17446
|
+
const [state, setState] = React4.useState({});
|
|
17447
|
+
const [status, setStatus] = React4.useState("ok");
|
|
17448
|
+
const load = React4.useCallback(async () => {
|
|
17449
|
+
setLoading(true);
|
|
17450
|
+
try {
|
|
17451
|
+
const res = await fetch("/api/seo-plugin/alt-text-audit", { credentials: "include", cache: "no-store" });
|
|
17452
|
+
if (res.status === 404) {
|
|
17453
|
+
setStatus("disabled");
|
|
17454
|
+
return;
|
|
17455
|
+
}
|
|
17456
|
+
if (res.status === 403) {
|
|
17457
|
+
setStatus("forbidden");
|
|
17458
|
+
return;
|
|
17459
|
+
}
|
|
17460
|
+
const json = await res.json();
|
|
17461
|
+
setStatus("ok");
|
|
17462
|
+
setItems(json.items || []);
|
|
17463
|
+
setMissingCount(json.missingCount || 0);
|
|
17464
|
+
setCollection(json.collection || "media");
|
|
17465
|
+
} catch {
|
|
17466
|
+
setItems([]);
|
|
17467
|
+
} finally {
|
|
17468
|
+
setLoading(false);
|
|
17469
|
+
}
|
|
17470
|
+
}, []);
|
|
17471
|
+
React4.useEffect(() => {
|
|
17472
|
+
void load();
|
|
17473
|
+
}, [load]);
|
|
17474
|
+
const setRow = (id, patch) => setState((prev) => ({ ...prev, [id]: { ...prev[id], ...patch } }));
|
|
17475
|
+
const generate = async (item) => {
|
|
17476
|
+
setRow(item.id, { busy: true, error: void 0 });
|
|
17477
|
+
try {
|
|
17478
|
+
const res = await fetch("/api/seo-plugin/ai-alt-text", {
|
|
17479
|
+
method: "POST",
|
|
17480
|
+
credentials: "include",
|
|
17481
|
+
headers: { "Content-Type": "application/json" },
|
|
17482
|
+
body: JSON.stringify({ collection, id: item.id, apply: false })
|
|
17483
|
+
});
|
|
17484
|
+
const json = await res.json();
|
|
17485
|
+
if (!res.ok) {
|
|
17486
|
+
setRow(item.id, { busy: false, error: json.code === "no_api_key" ? s.noKey : json.error || `Error ${res.status}` });
|
|
17487
|
+
return;
|
|
17488
|
+
}
|
|
17489
|
+
setRow(item.id, { busy: false, alt: json.alt });
|
|
17490
|
+
} catch (e) {
|
|
17491
|
+
setRow(item.id, { busy: false, error: e instanceof Error ? e.message : "Network error" });
|
|
17492
|
+
}
|
|
17493
|
+
};
|
|
17494
|
+
const apply = async (item) => {
|
|
17495
|
+
const alt = state[item.id]?.alt;
|
|
17496
|
+
if (!alt) return;
|
|
17497
|
+
setRow(item.id, { busy: true, error: void 0 });
|
|
17498
|
+
try {
|
|
17499
|
+
const res = await fetch("/api/seo-plugin/ai-alt-text", {
|
|
17500
|
+
method: "POST",
|
|
17501
|
+
credentials: "include",
|
|
17502
|
+
headers: { "Content-Type": "application/json" },
|
|
17503
|
+
body: JSON.stringify({ collection, id: item.id, apply: true, altText: alt })
|
|
17504
|
+
});
|
|
17505
|
+
const json = await res.json();
|
|
17506
|
+
if (!res.ok) {
|
|
17507
|
+
setRow(item.id, { busy: false, error: json.error || `Error ${res.status}` });
|
|
17508
|
+
return;
|
|
17509
|
+
}
|
|
17510
|
+
setRow(item.id, { busy: false, applied: true });
|
|
17511
|
+
} catch (e) {
|
|
17512
|
+
setRow(item.id, { busy: false, error: e instanceof Error ? e.message : "Network error" });
|
|
17513
|
+
}
|
|
17514
|
+
};
|
|
17515
|
+
const card = {
|
|
17516
|
+
padding: 16,
|
|
17517
|
+
borderRadius: 12,
|
|
17518
|
+
border: `1px solid ${C8.border}`,
|
|
17519
|
+
backgroundColor: C8.card,
|
|
17520
|
+
marginBottom: 20
|
|
17521
|
+
};
|
|
17522
|
+
const btn = (bg) => ({
|
|
17523
|
+
padding: "6px 10px",
|
|
17524
|
+
borderRadius: 6,
|
|
17525
|
+
border: `1px solid ${bg}`,
|
|
17526
|
+
backgroundColor: bg,
|
|
17527
|
+
color: "#fff",
|
|
17528
|
+
fontSize: 11,
|
|
17529
|
+
fontWeight: 700,
|
|
17530
|
+
cursor: "pointer"
|
|
17531
|
+
});
|
|
17532
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: card, children: [
|
|
17533
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, flexWrap: "wrap" }, children: [
|
|
17534
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
17535
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C8.text }, children: s.title }),
|
|
17536
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C8.sub, marginTop: 2 }, children: s.subtitle })
|
|
17537
|
+
] }),
|
|
17538
|
+
status === "ok" && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void load(), style: btn(C8.sub), children: s.refresh })
|
|
17539
|
+
] }),
|
|
17540
|
+
status === "forbidden" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C8.sub }, children: s.forbidden }),
|
|
17541
|
+
status === "disabled" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 12, fontSize: 13, color: C8.sub }, children: s.disabled }),
|
|
17542
|
+
status === "ok" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 12 }, children: [
|
|
17543
|
+
loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C8.sub }, children: s.loading }),
|
|
17544
|
+
!loading && items && items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: C8.sub }, children: s.none }),
|
|
17545
|
+
!loading && items && items.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
17546
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: C8.sub, marginBottom: 10 }, children: [
|
|
17547
|
+
missingCount,
|
|
17548
|
+
" ",
|
|
17549
|
+
s.missing
|
|
17550
|
+
] }),
|
|
17551
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 10 }, children: items.map((item) => {
|
|
17552
|
+
const rs = state[item.id] || {};
|
|
17553
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17554
|
+
"div",
|
|
17555
|
+
{
|
|
17556
|
+
style: {
|
|
17557
|
+
display: "flex",
|
|
17558
|
+
gap: 12,
|
|
17559
|
+
alignItems: "center",
|
|
17560
|
+
padding: 8,
|
|
17561
|
+
borderRadius: 8,
|
|
17562
|
+
border: `1px solid ${C8.border}`,
|
|
17563
|
+
backgroundColor: C8.bg
|
|
17564
|
+
},
|
|
17565
|
+
children: [
|
|
17566
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17567
|
+
"img",
|
|
17568
|
+
{
|
|
17569
|
+
src: item.url,
|
|
17570
|
+
alt: "",
|
|
17571
|
+
style: { width: 48, height: 48, objectFit: "cover", borderRadius: 6, flexShrink: 0, border: `1px solid ${C8.border}` }
|
|
17572
|
+
}
|
|
17573
|
+
),
|
|
17574
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
17575
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: C8.sub, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: item.filename }),
|
|
17576
|
+
rs.alt !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
17577
|
+
"input",
|
|
17578
|
+
{
|
|
17579
|
+
value: rs.alt,
|
|
17580
|
+
onChange: (e) => setRow(item.id, { alt: e.target.value }),
|
|
17581
|
+
disabled: rs.applied,
|
|
17582
|
+
maxLength: 125,
|
|
17583
|
+
style: {
|
|
17584
|
+
width: "100%",
|
|
17585
|
+
marginTop: 4,
|
|
17586
|
+
padding: "4px 8px",
|
|
17587
|
+
fontSize: 12,
|
|
17588
|
+
borderRadius: 6,
|
|
17589
|
+
border: `1px solid ${C8.border}`,
|
|
17590
|
+
backgroundColor: C8.bg,
|
|
17591
|
+
color: C8.text
|
|
17592
|
+
}
|
|
17593
|
+
}
|
|
17594
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C8.sub, marginTop: 4, fontStyle: "italic" }, children: "\u2014" }),
|
|
17595
|
+
rs.error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: C8.red, marginTop: 2 }, children: rs.error })
|
|
17596
|
+
] }),
|
|
17597
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flexShrink: 0 }, children: rs.applied ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 11, fontWeight: 700, color: C8.green }, children: s.applied }) : rs.alt !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void apply(item), disabled: rs.busy, style: btn(C8.green), children: rs.busy ? s.generating : s.apply }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void generate(item), disabled: rs.busy, style: btn(C8.violet), children: rs.busy ? s.generating : s.generate }) })
|
|
17598
|
+
]
|
|
17599
|
+
},
|
|
17600
|
+
item.id
|
|
17601
|
+
);
|
|
17602
|
+
}) })
|
|
17603
|
+
] })
|
|
17604
|
+
] })
|
|
17605
|
+
] });
|
|
17606
|
+
}
|
|
16971
17607
|
var V8 = {
|
|
16972
17608
|
text: "var(--theme-text, #1a1a1a)",
|
|
16973
17609
|
textSecondary: "var(--theme-elevation-600, #6b7280)",
|
|
@@ -17382,6 +18018,9 @@ function PerformanceView() {
|
|
|
17382
18018
|
),
|
|
17383
18019
|
/* @__PURE__ */ jsxRuntime.jsx(CoreWebVitalsPanel, { locale }),
|
|
17384
18020
|
/* @__PURE__ */ jsxRuntime.jsx(GscPanel, { locale }),
|
|
18021
|
+
/* @__PURE__ */ jsxRuntime.jsx(RankTrackingPanel, { locale }),
|
|
18022
|
+
/* @__PURE__ */ jsxRuntime.jsx(AlertsPanel, { locale }),
|
|
18023
|
+
/* @__PURE__ */ jsxRuntime.jsx(AltTextPanel, { locale }),
|
|
17385
18024
|
showImport && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17386
18025
|
"div",
|
|
17387
18026
|
{
|
|
@@ -17905,6 +18544,183 @@ function PerformanceView() {
|
|
|
17905
18544
|
}
|
|
17906
18545
|
);
|
|
17907
18546
|
}
|
|
18547
|
+
var C9 = {
|
|
18548
|
+
text: "var(--theme-text, #1a1a1a)",
|
|
18549
|
+
sub: "var(--theme-elevation-600, #6b7280)",
|
|
18550
|
+
card: "var(--theme-elevation-50, #f9fafb)",
|
|
18551
|
+
bg: "var(--theme-elevation-0, #fff)",
|
|
18552
|
+
border: "var(--theme-elevation-200, #e5e7eb)",
|
|
18553
|
+
violet: "#7c3aed",
|
|
18554
|
+
red: "#ef4444",
|
|
18555
|
+
blue: "#3b82f6"
|
|
18556
|
+
};
|
|
18557
|
+
var S6 = {
|
|
18558
|
+
fr: {
|
|
18559
|
+
title: "Brief de contenu IA",
|
|
18560
|
+
subtitle: "G\xE9n\xE8re un plan r\xE9dactionnel optimis\xE9 pour un mot-cl\xE9 (plan, entit\xE9s, questions, longueur cible).",
|
|
18561
|
+
placeholder: "Mot-cl\xE9 cible (ex : plombier paris)",
|
|
18562
|
+
generate: "G\xE9n\xE9rer le brief",
|
|
18563
|
+
generating: "G\xE9n\xE9ration\u2026",
|
|
18564
|
+
outline: "Plan sugg\xE9r\xE9",
|
|
18565
|
+
entities: "Entit\xE9s / termes \xE0 couvrir",
|
|
18566
|
+
questions: "Questions \xE0 traiter",
|
|
18567
|
+
links: "Id\xE9es de liens internes",
|
|
18568
|
+
words: "Longueur recommand\xE9e",
|
|
18569
|
+
wordsUnit: "mots",
|
|
18570
|
+
notes: "Conseils",
|
|
18571
|
+
noKey: "Cl\xE9 API Claude requise (ANTHROPIC_API_KEY).",
|
|
18572
|
+
disabled: "Fonction IA d\xE9sactiv\xE9e (features.aiFeatures)."
|
|
18573
|
+
},
|
|
18574
|
+
en: {
|
|
18575
|
+
title: "AI content brief",
|
|
18576
|
+
subtitle: "Generate an optimized writing brief for a keyword (outline, entities, questions, target length).",
|
|
18577
|
+
placeholder: "Target keyword (e.g. paris plumber)",
|
|
18578
|
+
generate: "Generate brief",
|
|
18579
|
+
generating: "Generating\u2026",
|
|
18580
|
+
outline: "Suggested outline",
|
|
18581
|
+
entities: "Entities / terms to cover",
|
|
18582
|
+
questions: "Questions to answer",
|
|
18583
|
+
links: "Internal link ideas",
|
|
18584
|
+
words: "Recommended length",
|
|
18585
|
+
wordsUnit: "words",
|
|
18586
|
+
notes: "Tips",
|
|
18587
|
+
noKey: "Claude API key required (ANTHROPIC_API_KEY).",
|
|
18588
|
+
disabled: "AI feature disabled (features.aiFeatures)."
|
|
18589
|
+
}
|
|
18590
|
+
};
|
|
18591
|
+
function ContentBriefPanel({ locale }) {
|
|
18592
|
+
const s = S6[locale] ?? S6.fr;
|
|
18593
|
+
const [keyword, setKeyword] = React4.useState("");
|
|
18594
|
+
const [brief, setBrief] = React4.useState(null);
|
|
18595
|
+
const [busy, setBusy] = React4.useState(false);
|
|
18596
|
+
const [error, setError] = React4.useState(null);
|
|
18597
|
+
const generate = async () => {
|
|
18598
|
+
if (!keyword.trim()) return;
|
|
18599
|
+
setBusy(true);
|
|
18600
|
+
setError(null);
|
|
18601
|
+
setBrief(null);
|
|
18602
|
+
try {
|
|
18603
|
+
const res = await fetch("/api/seo-plugin/ai-content-brief", {
|
|
18604
|
+
method: "POST",
|
|
18605
|
+
credentials: "include",
|
|
18606
|
+
headers: { "Content-Type": "application/json" },
|
|
18607
|
+
body: JSON.stringify({ keyword: keyword.trim() })
|
|
18608
|
+
});
|
|
18609
|
+
if (res.status === 404) {
|
|
18610
|
+
setError(s.disabled);
|
|
18611
|
+
return;
|
|
18612
|
+
}
|
|
18613
|
+
const json = await res.json();
|
|
18614
|
+
if (!res.ok) {
|
|
18615
|
+
setError(json.code === "no_api_key" ? s.noKey : json.error || `Error ${res.status}`);
|
|
18616
|
+
return;
|
|
18617
|
+
}
|
|
18618
|
+
setBrief(json.brief);
|
|
18619
|
+
} catch (e) {
|
|
18620
|
+
setError(e instanceof Error ? e.message : "Network error");
|
|
18621
|
+
} finally {
|
|
18622
|
+
setBusy(false);
|
|
18623
|
+
}
|
|
18624
|
+
};
|
|
18625
|
+
const card = {
|
|
18626
|
+
padding: 16,
|
|
18627
|
+
borderRadius: 12,
|
|
18628
|
+
border: `1px solid ${C9.border}`,
|
|
18629
|
+
backgroundColor: C9.card,
|
|
18630
|
+
marginBottom: 20
|
|
18631
|
+
};
|
|
18632
|
+
const chip = {
|
|
18633
|
+
display: "inline-block",
|
|
18634
|
+
fontSize: 11,
|
|
18635
|
+
padding: "3px 8px",
|
|
18636
|
+
borderRadius: 999,
|
|
18637
|
+
backgroundColor: "rgba(59,130,246,0.12)",
|
|
18638
|
+
color: C9.blue,
|
|
18639
|
+
border: `1px solid ${C9.border}`,
|
|
18640
|
+
margin: "0 6px 6px 0"
|
|
18641
|
+
};
|
|
18642
|
+
const h4 = { fontSize: 12, fontWeight: 800, color: C9.text, margin: "14px 0 6px", textTransform: "uppercase" };
|
|
18643
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: card, children: [
|
|
18644
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 16, fontWeight: 800, color: C9.text }, children: s.title }),
|
|
18645
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: C9.sub, marginTop: 2, marginBottom: 12 }, children: s.subtitle }),
|
|
18646
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
|
|
18647
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18648
|
+
"input",
|
|
18649
|
+
{
|
|
18650
|
+
value: keyword,
|
|
18651
|
+
onChange: (e) => setKeyword(e.target.value),
|
|
18652
|
+
onKeyDown: (e) => {
|
|
18653
|
+
if (e.key === "Enter") void generate();
|
|
18654
|
+
},
|
|
18655
|
+
placeholder: s.placeholder,
|
|
18656
|
+
style: {
|
|
18657
|
+
flex: 1,
|
|
18658
|
+
minWidth: 220,
|
|
18659
|
+
padding: "8px 12px",
|
|
18660
|
+
fontSize: 13,
|
|
18661
|
+
borderRadius: 8,
|
|
18662
|
+
border: `1px solid ${C9.border}`,
|
|
18663
|
+
backgroundColor: C9.bg,
|
|
18664
|
+
color: C9.text
|
|
18665
|
+
}
|
|
18666
|
+
}
|
|
18667
|
+
),
|
|
18668
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18669
|
+
"button",
|
|
18670
|
+
{
|
|
18671
|
+
type: "button",
|
|
18672
|
+
onClick: () => void generate(),
|
|
18673
|
+
disabled: busy || !keyword.trim(),
|
|
18674
|
+
style: {
|
|
18675
|
+
padding: "8px 14px",
|
|
18676
|
+
borderRadius: 8,
|
|
18677
|
+
border: `1px solid ${C9.violet}`,
|
|
18678
|
+
backgroundColor: C9.violet,
|
|
18679
|
+
color: "#fff",
|
|
18680
|
+
fontSize: 12,
|
|
18681
|
+
fontWeight: 700,
|
|
18682
|
+
cursor: busy || !keyword.trim() ? "not-allowed" : "pointer",
|
|
18683
|
+
opacity: busy || !keyword.trim() ? 0.6 : 1
|
|
18684
|
+
},
|
|
18685
|
+
children: busy ? s.generating : `\u2728 ${s.generate}`
|
|
18686
|
+
}
|
|
18687
|
+
)
|
|
18688
|
+
] }),
|
|
18689
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: C9.red, fontSize: 13, fontWeight: 600, marginTop: 10 }, children: error }),
|
|
18690
|
+
brief && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 8 }, children: [
|
|
18691
|
+
brief.recommendedWordCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 12, color: C9.sub, marginTop: 10 }, children: [
|
|
18692
|
+
s.words,
|
|
18693
|
+
": ",
|
|
18694
|
+
/* @__PURE__ */ jsxRuntime.jsxs("b", { style: { color: C9.text }, children: [
|
|
18695
|
+
"~",
|
|
18696
|
+
brief.recommendedWordCount,
|
|
18697
|
+
" ",
|
|
18698
|
+
s.wordsUnit
|
|
18699
|
+
] })
|
|
18700
|
+
] }),
|
|
18701
|
+
brief.outline.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18702
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: h4, children: s.outline }),
|
|
18703
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: C9.text, lineHeight: 1.6 }, children: brief.outline.map((o, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { style: { marginLeft: o.level === "h3" ? 18 : 0, color: o.level === "h3" ? C9.sub : C9.text, fontWeight: o.level === "h2" ? 700 : 400 }, children: o.text }, i)) })
|
|
18704
|
+
] }),
|
|
18705
|
+
brief.entities.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18706
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: h4, children: s.entities }),
|
|
18707
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: brief.entities.map((e, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { style: chip, children: e }, i)) })
|
|
18708
|
+
] }),
|
|
18709
|
+
brief.questions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18710
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: h4, children: s.questions }),
|
|
18711
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 13, color: C9.text, lineHeight: 1.6 }, children: brief.questions.map((q, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: q }, i)) })
|
|
18712
|
+
] }),
|
|
18713
|
+
brief.internalLinkIdeas.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18714
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: h4, children: s.links }),
|
|
18715
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: brief.internalLinkIdeas.map((l, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { style: chip, children: l }, i)) })
|
|
18716
|
+
] }),
|
|
18717
|
+
brief.notes.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
18718
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: h4, children: s.notes }),
|
|
18719
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: 18, fontSize: 12, color: C9.sub, lineHeight: 1.6 }, children: brief.notes.map((n, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: n }, i)) })
|
|
18720
|
+
] })
|
|
18721
|
+
] })
|
|
18722
|
+
] });
|
|
18723
|
+
}
|
|
17908
18724
|
var V9 = {
|
|
17909
18725
|
text: "var(--theme-text, #1a1a1a)",
|
|
17910
18726
|
textSecondary: "var(--theme-elevation-600, #6b7280)",
|
|
@@ -18267,6 +19083,7 @@ function KeywordResearchView() {
|
|
|
18267
19083
|
]
|
|
18268
19084
|
}
|
|
18269
19085
|
),
|
|
19086
|
+
/* @__PURE__ */ jsxRuntime.jsx(ContentBriefPanel, { locale }),
|
|
18270
19087
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18271
19088
|
"div",
|
|
18272
19089
|
{
|
|
@@ -19041,7 +19858,7 @@ var controlBtnStyle = {
|
|
|
19041
19858
|
cursor: "pointer",
|
|
19042
19859
|
lineHeight: 1.4
|
|
19043
19860
|
};
|
|
19044
|
-
var
|
|
19861
|
+
var C10 = {
|
|
19045
19862
|
cyan: "#00E5FF",
|
|
19046
19863
|
black: "#000",
|
|
19047
19864
|
green: "#22c55e",
|
|
@@ -19056,10 +19873,10 @@ var C6 = {
|
|
|
19056
19873
|
var TITLE_MIN = 30;
|
|
19057
19874
|
var TITLE_MAX = 60;
|
|
19058
19875
|
function getCharColor(len) {
|
|
19059
|
-
if (len === 0) return
|
|
19060
|
-
if (len >= TITLE_MIN && len <= TITLE_MAX) return
|
|
19061
|
-
if (len > 0 && len < TITLE_MIN) return
|
|
19062
|
-
return
|
|
19876
|
+
if (len === 0) return C10.textSecondary;
|
|
19877
|
+
if (len >= TITLE_MIN && len <= TITLE_MAX) return C10.green;
|
|
19878
|
+
if (len > 0 && len < TITLE_MIN) return C10.orange;
|
|
19879
|
+
return C10.red;
|
|
19063
19880
|
}
|
|
19064
19881
|
function getProgressPercent(len) {
|
|
19065
19882
|
if (len === 0) return 0;
|
|
@@ -19067,9 +19884,9 @@ function getProgressPercent(len) {
|
|
|
19067
19884
|
}
|
|
19068
19885
|
function getProgressColor(len) {
|
|
19069
19886
|
if (len === 0) return "var(--theme-elevation-200, #e5e7eb)";
|
|
19070
|
-
if (len >= TITLE_MIN && len <= TITLE_MAX) return
|
|
19071
|
-
if (len < TITLE_MIN) return
|
|
19072
|
-
return
|
|
19887
|
+
if (len >= TITLE_MIN && len <= TITLE_MAX) return C10.green;
|
|
19888
|
+
if (len < TITLE_MIN) return C10.orange;
|
|
19889
|
+
return C10.red;
|
|
19073
19890
|
}
|
|
19074
19891
|
function MetaTitleField({
|
|
19075
19892
|
path,
|
|
@@ -19140,7 +19957,7 @@ function MetaTitleField({
|
|
|
19140
19957
|
style: {
|
|
19141
19958
|
fontSize: 13,
|
|
19142
19959
|
fontWeight: 700,
|
|
19143
|
-
color:
|
|
19960
|
+
color: C10.textPrimary
|
|
19144
19961
|
},
|
|
19145
19962
|
children: t.metaTitle.label
|
|
19146
19963
|
}
|
|
@@ -19180,9 +19997,9 @@ function MetaTitleField({
|
|
|
19180
19997
|
fontSize: 14,
|
|
19181
19998
|
fontFamily: "inherit",
|
|
19182
19999
|
borderRadius: 8,
|
|
19183
|
-
border: `2px solid ${
|
|
19184
|
-
backgroundColor:
|
|
19185
|
-
color:
|
|
20000
|
+
border: `2px solid ${C10.border}`,
|
|
20001
|
+
backgroundColor: C10.surfaceBg,
|
|
20002
|
+
color: C10.textPrimary,
|
|
19186
20003
|
outline: "none",
|
|
19187
20004
|
boxShadow: "2px 2px 0 0 var(--theme-border-color, rgba(0,0,0,1))"
|
|
19188
20005
|
}
|
|
@@ -19200,9 +20017,9 @@ function MetaTitleField({
|
|
|
19200
20017
|
gap: 5,
|
|
19201
20018
|
padding: "8px 14px",
|
|
19202
20019
|
borderRadius: 8,
|
|
19203
|
-
border: `2px solid ${
|
|
19204
|
-
backgroundColor: loading ?
|
|
19205
|
-
color: loading ?
|
|
20020
|
+
border: `2px solid ${C10.border}`,
|
|
20021
|
+
backgroundColor: loading ? C10.surface50 : C10.cyan,
|
|
20022
|
+
color: loading ? C10.textSecondary : C10.black,
|
|
19206
20023
|
fontWeight: 800,
|
|
19207
20024
|
fontSize: 11,
|
|
19208
20025
|
textTransform: "uppercase",
|
|
@@ -19249,7 +20066,7 @@ function MetaTitleField({
|
|
|
19249
20066
|
justifyContent: "space-between",
|
|
19250
20067
|
marginTop: 4,
|
|
19251
20068
|
fontSize: 10,
|
|
19252
|
-
color:
|
|
20069
|
+
color: C10.textSecondary
|
|
19253
20070
|
},
|
|
19254
20071
|
children: [
|
|
19255
20072
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
@@ -19283,9 +20100,9 @@ function MetaTitleField({
|
|
|
19283
20100
|
borderRadius: 6,
|
|
19284
20101
|
fontSize: 11,
|
|
19285
20102
|
fontWeight: 600,
|
|
19286
|
-
color:
|
|
20103
|
+
color: C10.red,
|
|
19287
20104
|
backgroundColor: "rgba(239,68,68,0.08)",
|
|
19288
|
-
border: `1px solid ${
|
|
20105
|
+
border: `1px solid ${C10.red}`
|
|
19289
20106
|
},
|
|
19290
20107
|
children: error
|
|
19291
20108
|
}
|
|
@@ -19294,7 +20111,7 @@ function MetaTitleField({
|
|
|
19294
20111
|
}
|
|
19295
20112
|
);
|
|
19296
20113
|
}
|
|
19297
|
-
var
|
|
20114
|
+
var C11 = {
|
|
19298
20115
|
cyan: "#00E5FF",
|
|
19299
20116
|
black: "#000",
|
|
19300
20117
|
green: "#22c55e",
|
|
@@ -19309,10 +20126,10 @@ var C7 = {
|
|
|
19309
20126
|
var DESC_MIN = 120;
|
|
19310
20127
|
var DESC_MAX = 160;
|
|
19311
20128
|
function getCharColor2(len) {
|
|
19312
|
-
if (len === 0) return
|
|
19313
|
-
if (len >= DESC_MIN && len <= DESC_MAX) return
|
|
19314
|
-
if (len > 0 && len < DESC_MIN) return
|
|
19315
|
-
return
|
|
20129
|
+
if (len === 0) return C11.textSecondary;
|
|
20130
|
+
if (len >= DESC_MIN && len <= DESC_MAX) return C11.green;
|
|
20131
|
+
if (len > 0 && len < DESC_MIN) return C11.orange;
|
|
20132
|
+
return C11.red;
|
|
19316
20133
|
}
|
|
19317
20134
|
function getProgressPercent2(len) {
|
|
19318
20135
|
if (len === 0) return 0;
|
|
@@ -19320,9 +20137,9 @@ function getProgressPercent2(len) {
|
|
|
19320
20137
|
}
|
|
19321
20138
|
function getProgressColor2(len) {
|
|
19322
20139
|
if (len === 0) return "var(--theme-elevation-200, #e5e7eb)";
|
|
19323
|
-
if (len >= DESC_MIN && len <= DESC_MAX) return
|
|
19324
|
-
if (len < DESC_MIN) return
|
|
19325
|
-
return
|
|
20140
|
+
if (len >= DESC_MIN && len <= DESC_MAX) return C11.green;
|
|
20141
|
+
if (len < DESC_MIN) return C11.orange;
|
|
20142
|
+
return C11.red;
|
|
19326
20143
|
}
|
|
19327
20144
|
function MetaDescriptionField({
|
|
19328
20145
|
path,
|
|
@@ -19393,7 +20210,7 @@ function MetaDescriptionField({
|
|
|
19393
20210
|
style: {
|
|
19394
20211
|
fontSize: 13,
|
|
19395
20212
|
fontWeight: 700,
|
|
19396
|
-
color:
|
|
20213
|
+
color: C11.textPrimary
|
|
19397
20214
|
},
|
|
19398
20215
|
children: t.metaDescription.label
|
|
19399
20216
|
}
|
|
@@ -19433,9 +20250,9 @@ function MetaDescriptionField({
|
|
|
19433
20250
|
fontSize: 14,
|
|
19434
20251
|
fontFamily: "inherit",
|
|
19435
20252
|
borderRadius: 8,
|
|
19436
|
-
border: `2px solid ${
|
|
19437
|
-
backgroundColor:
|
|
19438
|
-
color:
|
|
20253
|
+
border: `2px solid ${C11.border}`,
|
|
20254
|
+
backgroundColor: C11.surfaceBg,
|
|
20255
|
+
color: C11.textPrimary,
|
|
19439
20256
|
outline: "none",
|
|
19440
20257
|
resize: "vertical",
|
|
19441
20258
|
lineHeight: 1.5,
|
|
@@ -19455,9 +20272,9 @@ function MetaDescriptionField({
|
|
|
19455
20272
|
gap: 5,
|
|
19456
20273
|
padding: "8px 14px",
|
|
19457
20274
|
borderRadius: 8,
|
|
19458
|
-
border: `2px solid ${
|
|
19459
|
-
backgroundColor: loading ?
|
|
19460
|
-
color: loading ?
|
|
20275
|
+
border: `2px solid ${C11.border}`,
|
|
20276
|
+
backgroundColor: loading ? C11.surface50 : C11.cyan,
|
|
20277
|
+
color: loading ? C11.textSecondary : C11.black,
|
|
19461
20278
|
fontWeight: 800,
|
|
19462
20279
|
fontSize: 11,
|
|
19463
20280
|
textTransform: "uppercase",
|
|
@@ -19505,7 +20322,7 @@ function MetaDescriptionField({
|
|
|
19505
20322
|
justifyContent: "space-between",
|
|
19506
20323
|
marginTop: 4,
|
|
19507
20324
|
fontSize: 10,
|
|
19508
|
-
color:
|
|
20325
|
+
color: C11.textSecondary
|
|
19509
20326
|
},
|
|
19510
20327
|
children: [
|
|
19511
20328
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
@@ -19539,9 +20356,9 @@ function MetaDescriptionField({
|
|
|
19539
20356
|
borderRadius: 6,
|
|
19540
20357
|
fontSize: 11,
|
|
19541
20358
|
fontWeight: 600,
|
|
19542
|
-
color:
|
|
20359
|
+
color: C11.red,
|
|
19543
20360
|
backgroundColor: "rgba(239,68,68,0.08)",
|
|
19544
|
-
border: `1px solid ${
|
|
20361
|
+
border: `1px solid ${C11.red}`
|
|
19545
20362
|
},
|
|
19546
20363
|
children: error
|
|
19547
20364
|
}
|
|
@@ -19550,7 +20367,7 @@ function MetaDescriptionField({
|
|
|
19550
20367
|
}
|
|
19551
20368
|
);
|
|
19552
20369
|
}
|
|
19553
|
-
var
|
|
20370
|
+
var C12 = {
|
|
19554
20371
|
cyan: "#00E5FF",
|
|
19555
20372
|
black: "#000",
|
|
19556
20373
|
white: "#fff",
|
|
@@ -19627,8 +20444,8 @@ function MetaImageField({
|
|
|
19627
20444
|
gap: 10,
|
|
19628
20445
|
padding: "10px 14px",
|
|
19629
20446
|
borderRadius: 8,
|
|
19630
|
-
border: `2px solid ${
|
|
19631
|
-
backgroundColor:
|
|
20447
|
+
border: `2px solid ${C12.border}`,
|
|
20448
|
+
backgroundColor: C12.surfaceBg,
|
|
19632
20449
|
boxShadow: "2px 2px 0 0 var(--theme-border-color, rgba(0,0,0,1))"
|
|
19633
20450
|
},
|
|
19634
20451
|
children: [
|
|
@@ -19647,7 +20464,7 @@ function MetaImageField({
|
|
|
19647
20464
|
fontWeight: 900,
|
|
19648
20465
|
backgroundColor: hasImage ? "rgba(34,197,94,0.15)" : "rgba(255,138,0,0.15)",
|
|
19649
20466
|
color: hasImage ? "#16a34a" : "#d97706",
|
|
19650
|
-
border: `1px solid ${hasImage ?
|
|
20467
|
+
border: `1px solid ${hasImage ? C12.green : C12.orange}`
|
|
19651
20468
|
},
|
|
19652
20469
|
children: hasImage ? "\u2713" : "!"
|
|
19653
20470
|
}
|
|
@@ -19659,7 +20476,7 @@ function MetaImageField({
|
|
|
19659
20476
|
style: {
|
|
19660
20477
|
fontSize: 12,
|
|
19661
20478
|
fontWeight: 700,
|
|
19662
|
-
color:
|
|
20479
|
+
color: C12.textPrimary
|
|
19663
20480
|
},
|
|
19664
20481
|
children: t.metaImage.label
|
|
19665
20482
|
}
|
|
@@ -19669,7 +20486,7 @@ function MetaImageField({
|
|
|
19669
20486
|
{
|
|
19670
20487
|
style: {
|
|
19671
20488
|
fontSize: 10,
|
|
19672
|
-
color:
|
|
20489
|
+
color: C12.textSecondary,
|
|
19673
20490
|
lineHeight: 1.4
|
|
19674
20491
|
},
|
|
19675
20492
|
children: hasImage ? t.metaImage.imageSet : t.metaImage.noImage
|
|
@@ -19689,9 +20506,9 @@ function MetaImageField({
|
|
|
19689
20506
|
gap: 5,
|
|
19690
20507
|
padding: "8px 14px",
|
|
19691
20508
|
borderRadius: 8,
|
|
19692
|
-
border: `2px solid ${
|
|
19693
|
-
backgroundColor: loading ?
|
|
19694
|
-
color: loading ?
|
|
20509
|
+
border: `2px solid ${C12.border}`,
|
|
20510
|
+
backgroundColor: loading ? C12.surface50 : success ? C12.green : C12.cyan,
|
|
20511
|
+
color: loading ? C12.textSecondary : success ? C12.white : C12.black,
|
|
19695
20512
|
fontWeight: 800,
|
|
19696
20513
|
fontSize: 11,
|
|
19697
20514
|
textTransform: "uppercase",
|
|
@@ -19718,9 +20535,9 @@ function MetaImageField({
|
|
|
19718
20535
|
borderRadius: 6,
|
|
19719
20536
|
fontSize: 11,
|
|
19720
20537
|
fontWeight: 600,
|
|
19721
|
-
color:
|
|
20538
|
+
color: C12.red,
|
|
19722
20539
|
backgroundColor: "rgba(239,68,68,0.08)",
|
|
19723
|
-
border: `1px solid ${
|
|
20540
|
+
border: `1px solid ${C12.red}`
|
|
19724
20541
|
},
|
|
19725
20542
|
children: error
|
|
19726
20543
|
}
|
|
@@ -19729,7 +20546,7 @@ function MetaImageField({
|
|
|
19729
20546
|
}
|
|
19730
20547
|
);
|
|
19731
20548
|
}
|
|
19732
|
-
var
|
|
20549
|
+
var C13 = {
|
|
19733
20550
|
black: "#000",
|
|
19734
20551
|
white: "#fff",
|
|
19735
20552
|
green: "#22c55e",
|
|
@@ -19743,15 +20560,15 @@ var C9 = {
|
|
|
19743
20560
|
function getCompletenessColor(count) {
|
|
19744
20561
|
switch (count) {
|
|
19745
20562
|
case 0:
|
|
19746
|
-
return
|
|
20563
|
+
return C13.red;
|
|
19747
20564
|
case 1:
|
|
19748
|
-
return
|
|
20565
|
+
return C13.orange;
|
|
19749
20566
|
case 2:
|
|
19750
|
-
return
|
|
20567
|
+
return C13.yellow;
|
|
19751
20568
|
case 3:
|
|
19752
|
-
return
|
|
20569
|
+
return C13.green;
|
|
19753
20570
|
default:
|
|
19754
|
-
return
|
|
20571
|
+
return C13.textSecondary;
|
|
19755
20572
|
}
|
|
19756
20573
|
}
|
|
19757
20574
|
function getCompletenessLabel(count, ov) {
|
|
@@ -19809,8 +20626,8 @@ function OverviewField({
|
|
|
19809
20626
|
fontFamily: "var(--font-body, Inter, system-ui, sans-serif)",
|
|
19810
20627
|
padding: "12px 14px",
|
|
19811
20628
|
borderRadius: 10,
|
|
19812
|
-
border: `2px solid ${
|
|
19813
|
-
backgroundColor:
|
|
20629
|
+
border: `2px solid ${C13.border}`,
|
|
20630
|
+
backgroundColor: C13.surfaceBg,
|
|
19814
20631
|
boxShadow: "3px 3px 0 0 var(--theme-border-color, rgba(0,0,0,1))",
|
|
19815
20632
|
marginBottom: 12
|
|
19816
20633
|
},
|
|
@@ -19833,7 +20650,7 @@ function OverviewField({
|
|
|
19833
20650
|
fontWeight: 800,
|
|
19834
20651
|
textTransform: "uppercase",
|
|
19835
20652
|
letterSpacing: "0.04em",
|
|
19836
|
-
color:
|
|
20653
|
+
color: C13.textPrimary
|
|
19837
20654
|
},
|
|
19838
20655
|
children: t.overview.metaCompleteness
|
|
19839
20656
|
}
|
|
@@ -19848,8 +20665,8 @@ function OverviewField({
|
|
|
19848
20665
|
fontSize: 11,
|
|
19849
20666
|
fontWeight: 800,
|
|
19850
20667
|
backgroundColor: completenessColor,
|
|
19851
|
-
color: completenessColor ===
|
|
19852
|
-
border: `2px solid ${
|
|
20668
|
+
color: completenessColor === C13.yellow ? C13.black : C13.white,
|
|
20669
|
+
border: `2px solid ${C13.border}`,
|
|
19853
20670
|
textTransform: "uppercase",
|
|
19854
20671
|
letterSpacing: "0.03em"
|
|
19855
20672
|
},
|
|
@@ -19947,7 +20764,7 @@ function OverviewField({
|
|
|
19947
20764
|
style: {
|
|
19948
20765
|
fontSize: 12,
|
|
19949
20766
|
fontWeight: 600,
|
|
19950
|
-
color: item.filled ?
|
|
20767
|
+
color: item.filled ? C13.textPrimary : C13.textSecondary
|
|
19951
20768
|
},
|
|
19952
20769
|
children: item.label
|
|
19953
20770
|
}
|
|
@@ -19959,7 +20776,7 @@ function OverviewField({
|
|
|
19959
20776
|
marginLeft: "auto",
|
|
19960
20777
|
fontSize: 10,
|
|
19961
20778
|
fontWeight: 700,
|
|
19962
|
-
color: item.filled ?
|
|
20779
|
+
color: item.filled ? C13.green : C13.red,
|
|
19963
20780
|
textTransform: "uppercase",
|
|
19964
20781
|
letterSpacing: "0.03em"
|
|
19965
20782
|
},
|
|
@@ -19976,7 +20793,7 @@ function OverviewField({
|
|
|
19976
20793
|
}
|
|
19977
20794
|
);
|
|
19978
20795
|
}
|
|
19979
|
-
var
|
|
20796
|
+
var C14 = {
|
|
19980
20797
|
cyan: "#00E5FF",
|
|
19981
20798
|
black: "#000",
|
|
19982
20799
|
white: "#fff",
|
|
@@ -19995,10 +20812,10 @@ var G = {
|
|
|
19995
20812
|
descGrey: "#4d5156",
|
|
19996
20813
|
faviconBg: "#e8eaed"};
|
|
19997
20814
|
function charCountColor2(len, min, max) {
|
|
19998
|
-
if (len >= min && len <= max) return
|
|
19999
|
-
if (len > 0 && len < min) return
|
|
20000
|
-
if (len > max) return
|
|
20001
|
-
return
|
|
20815
|
+
if (len >= min && len <= max) return C14.green;
|
|
20816
|
+
if (len > 0 && len < min) return C14.orange;
|
|
20817
|
+
if (len > max) return C14.red;
|
|
20818
|
+
return C14.textSecondary;
|
|
20002
20819
|
}
|
|
20003
20820
|
function truncateText(text, maxChars) {
|
|
20004
20821
|
if (text.length <= maxChars) return text;
|
|
@@ -20053,8 +20870,8 @@ function SerpPreview({
|
|
|
20053
20870
|
padding: "10px 12px",
|
|
20054
20871
|
cursor: "pointer",
|
|
20055
20872
|
borderRadius: 8,
|
|
20056
|
-
border: `2px solid ${
|
|
20057
|
-
backgroundColor:
|
|
20873
|
+
border: `2px solid ${C14.border}`,
|
|
20874
|
+
backgroundColor: C14.surface50,
|
|
20058
20875
|
userSelect: "none"
|
|
20059
20876
|
},
|
|
20060
20877
|
children: [
|
|
@@ -20069,7 +20886,7 @@ function SerpPreview({
|
|
|
20069
20886
|
fontWeight: 800,
|
|
20070
20887
|
textTransform: "uppercase",
|
|
20071
20888
|
letterSpacing: "0.04em",
|
|
20072
|
-
color:
|
|
20889
|
+
color: C14.textPrimary
|
|
20073
20890
|
},
|
|
20074
20891
|
children: [
|
|
20075
20892
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -20101,7 +20918,7 @@ function SerpPreview({
|
|
|
20101
20918
|
transition: "transform 0.2s",
|
|
20102
20919
|
display: "inline-block",
|
|
20103
20920
|
transform: open ? "rotate(90deg)" : "none",
|
|
20104
|
-
color:
|
|
20921
|
+
color: C14.textSecondary
|
|
20105
20922
|
},
|
|
20106
20923
|
children: "\u25B6"
|
|
20107
20924
|
}
|
|
@@ -20134,10 +20951,10 @@ function SerpPreview({
|
|
|
20134
20951
|
"div",
|
|
20135
20952
|
{
|
|
20136
20953
|
style: {
|
|
20137
|
-
backgroundColor:
|
|
20138
|
-
border: `2px solid ${
|
|
20954
|
+
backgroundColor: C14.white,
|
|
20955
|
+
border: `2px solid ${C14.border}`,
|
|
20139
20956
|
borderRadius: 12,
|
|
20140
|
-
boxShadow: `3px 3px 0 0 ${
|
|
20957
|
+
boxShadow: `3px 3px 0 0 ${C14.border}`,
|
|
20141
20958
|
padding: isDesktop ? 20 : 14,
|
|
20142
20959
|
maxWidth: isDesktop ? 650 : 380,
|
|
20143
20960
|
overflow: "hidden"
|
|
@@ -20200,7 +21017,7 @@ function SerpPreview({
|
|
|
20200
21017
|
style: {
|
|
20201
21018
|
fontSize: 14,
|
|
20202
21019
|
fontWeight: 400,
|
|
20203
|
-
color:
|
|
21020
|
+
color: C14.black,
|
|
20204
21021
|
lineHeight: 1.3,
|
|
20205
21022
|
whiteSpace: "nowrap",
|
|
20206
21023
|
overflow: "hidden",
|
|
@@ -20264,7 +21081,7 @@ function SerpPreview({
|
|
|
20264
21081
|
"span",
|
|
20265
21082
|
{
|
|
20266
21083
|
style: {
|
|
20267
|
-
color:
|
|
21084
|
+
color: C14.textSecondary,
|
|
20268
21085
|
fontStyle: "italic",
|
|
20269
21086
|
fontSize: titleFontSize - 2
|
|
20270
21087
|
},
|
|
@@ -20293,7 +21110,7 @@ function SerpPreview({
|
|
|
20293
21110
|
"span",
|
|
20294
21111
|
{
|
|
20295
21112
|
style: {
|
|
20296
|
-
color:
|
|
21113
|
+
color: C14.textSecondary,
|
|
20297
21114
|
fontStyle: "italic",
|
|
20298
21115
|
fontSize: descFontSize - 1
|
|
20299
21116
|
},
|
|
@@ -20326,7 +21143,7 @@ function SerpPreview({
|
|
|
20326
21143
|
fontSize: 11
|
|
20327
21144
|
},
|
|
20328
21145
|
children: [
|
|
20329
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color:
|
|
21146
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C14.textSecondary, fontWeight: 600 }, children: t.serpPreview.previewTitle }),
|
|
20330
21147
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20331
21148
|
"span",
|
|
20332
21149
|
{
|
|
@@ -20355,7 +21172,7 @@ function SerpPreview({
|
|
|
20355
21172
|
fontSize: 11
|
|
20356
21173
|
},
|
|
20357
21174
|
children: [
|
|
20358
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color:
|
|
21175
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C14.textSecondary, fontWeight: 600 }, children: t.serpPreview.previewDescription }),
|
|
20359
21176
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20360
21177
|
"span",
|
|
20361
21178
|
{
|
|
@@ -20384,14 +21201,14 @@ function SerpPreview({
|
|
|
20384
21201
|
fontSize: 11
|
|
20385
21202
|
},
|
|
20386
21203
|
children: [
|
|
20387
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color:
|
|
21204
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: C14.textSecondary, fontWeight: 600 }, children: t.serpPreview.url }),
|
|
20388
21205
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20389
21206
|
"span",
|
|
20390
21207
|
{
|
|
20391
21208
|
style: {
|
|
20392
21209
|
fontWeight: 700,
|
|
20393
21210
|
fontVariantNumeric: "tabular-nums",
|
|
20394
|
-
color: fullUrl.length <= 75 ?
|
|
21211
|
+
color: fullUrl.length <= 75 ? C14.green : C14.red
|
|
20395
21212
|
},
|
|
20396
21213
|
children: [
|
|
20397
21214
|
fullUrl.length,
|
|
@@ -20426,13 +21243,13 @@ function DeviceButton({
|
|
|
20426
21243
|
gap: 5,
|
|
20427
21244
|
padding: "4px 12px",
|
|
20428
21245
|
borderRadius: 6,
|
|
20429
|
-
border: `2px solid ${
|
|
21246
|
+
border: `2px solid ${C14.border}`,
|
|
20430
21247
|
fontSize: 11,
|
|
20431
21248
|
fontWeight: 700,
|
|
20432
21249
|
cursor: "pointer",
|
|
20433
|
-
backgroundColor: active ?
|
|
20434
|
-
color: active ?
|
|
20435
|
-
boxShadow: active ? `2px 2px 0 0 ${
|
|
21250
|
+
backgroundColor: active ? C14.cyan : C14.surfaceBg,
|
|
21251
|
+
color: active ? C14.black : C14.textPrimary,
|
|
21252
|
+
boxShadow: active ? `2px 2px 0 0 ${C14.border}` : "none",
|
|
20436
21253
|
transition: "background-color 0.15s"
|
|
20437
21254
|
},
|
|
20438
21255
|
children: [
|