@webnumseoagent/next 0.2.0 → 0.2.2
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/bin/cli.mjs +17 -9
- package/client.ts +1 -1
- package/dist/client.js +1 -1
- package/package.json +1 -1
package/bin/cli.mjs
CHANGED
|
@@ -370,13 +370,14 @@ async function init() {
|
|
|
370
370
|
log(`\n И смонтируй JSON-LD в layout (внутри <body>):\n \x1b[36mimport { SeoJsonLd } from "${importJsonld}";\n <SeoJsonLd route="/" />\x1b[0m`);
|
|
371
371
|
}
|
|
372
372
|
|
|
373
|
-
// 7. Блог (пакет-рендер, Фаза 3.1c) —
|
|
374
|
-
//
|
|
375
|
-
//
|
|
376
|
-
|
|
373
|
+
// 7. Блог (пакет-рендер, Фаза 3.1c) — ПО УМОЛЧАНИЮ: ставит роуты /blog и /blog/[slug] прямо при
|
|
374
|
+
// подключении сайта (opt-out флагом --no-blog). ensureFile идемпотентен и НЕ перезаписывает файлы,
|
|
375
|
+
// поэтому собственный блог сайта (свой app/blog/page.*) остаётся нетронутым. ПОСЛЕ авто-обёртки
|
|
376
|
+
// generateMetadata: у блог-роута свой generateMetadata (seoBlogPost), его НЕ оборачиваем seoMeta.
|
|
377
|
+
if (!args.includes("--no-blog")) {
|
|
377
378
|
const jsxExt = ext === "ts" ? "tsx" : "jsx";
|
|
378
379
|
const mdParam = ext === "ts" ? "{ params }: { params: { slug: string } }" : "{ params }";
|
|
379
|
-
await ensureFile(
|
|
380
|
+
const madeIndex = await ensureFile(
|
|
380
381
|
path.join(root, appDir, `blog/page.${jsxExt}`),
|
|
381
382
|
`import { SeoBlogIndex } from "${blogFor("blog/page.tsx")}";\nexport const revalidate = 300;\nexport default function BlogPage() {\n return <SeoBlogIndex title="Блог" />;\n}\n`,
|
|
382
383
|
);
|
|
@@ -388,16 +389,21 @@ async function init() {
|
|
|
388
389
|
const names = await fs.readdir(blogDir).catch(() => []);
|
|
389
390
|
blogDynConflict = names.some((n) => /^\[.*\]$/.test(n) && n !== "[slug]");
|
|
390
391
|
}
|
|
392
|
+
let madeArticle = false;
|
|
391
393
|
if (blogDynConflict) {
|
|
392
|
-
log(`\n \x1b[1mУ сайта уже есть app
|
|
394
|
+
log(`\n \x1b[1mУ сайта уже есть app/blog/[иной-сегмент]\x1b[0m — роут статьи /blog/[slug] не создаю (Next запрещает два динамических сегмента).`);
|
|
393
395
|
log(` Подключи статьи к своему сегменту вручную: \x1b[36mimport { seoBlogPost, SeoBlogArticle } from "${blogFor("blog/[slug]/page.tsx")}";\x1b[0m`);
|
|
394
396
|
} else {
|
|
395
|
-
await ensureFile(
|
|
397
|
+
madeArticle = await ensureFile(
|
|
396
398
|
path.join(root, appDir, `blog/[slug]/page.${jsxExt}`),
|
|
397
399
|
`import { notFound } from "next/navigation";\nimport { seoBlogPost, SeoBlogArticle } from "${blogFor("blog/[slug]/page.tsx")}";\nexport const revalidate = 300;\n\nexport async function generateMetadata(${mdParam}) {\n const post = await seoBlogPost(params.slug);\n if (!post) return {};\n return { title: post.title, description: post.excerpt, openGraph: { images: post.cover ? [post.cover] : [] } };\n}\n\nexport default async function BlogPostPage(${mdParam}) {\n const post = await seoBlogPost(params.slug);\n if (!post) notFound();\n return <SeoBlogArticle post={post} />;\n}\n`,
|
|
398
400
|
);
|
|
399
401
|
}
|
|
400
|
-
|
|
402
|
+
if (madeIndex || madeArticle) {
|
|
403
|
+
log(`\n \x1b[32m✓\x1b[0m Блог: роуты /blog (пакет-рендер) созданы. Настрой доставку + anon-ключ на платформе. (Отключить блог: \x1b[1m--no-blog\x1b[0m)`);
|
|
404
|
+
} else {
|
|
405
|
+
log(`\n \x1b[33mℹ\x1b[0m Блог: у сайта уже есть роуты /blog — не трогаю.`);
|
|
406
|
+
}
|
|
401
407
|
}
|
|
402
408
|
|
|
403
409
|
log("\n\x1b[1mЗатем:\x1b[0m задай эти же env-переменные в Vercel (Settings → Environment Variables) и сделай git push.\n");
|
|
@@ -466,5 +472,7 @@ async function findMetadataPages(dir, acc = []) {
|
|
|
466
472
|
if (cmd === "init") {
|
|
467
473
|
init().catch((e) => { console.error(e); process.exit(1); });
|
|
468
474
|
} else {
|
|
469
|
-
log("Использование: npx @webnumseoagent/next init [--site <id>] [--token <t>] [--api <url>] [--revalidate-secret <s>]");
|
|
475
|
+
log("Использование: npx @webnumseoagent/next init [--wrap] [--no-blog] [--site <id>] [--token <t>] [--api <url>] [--revalidate-secret <s>]");
|
|
476
|
+
log(" --wrap — авто-обернуть generateMetadata страниц (иначе печатает сниппеты)");
|
|
477
|
+
log(" --no-blog — не создавать роуты блога /blog (по умолчанию блог создаётся)");
|
|
470
478
|
}
|
package/client.ts
CHANGED
|
@@ -260,7 +260,7 @@ export async function seoSitemapXml(path: string): Promise<string> {
|
|
|
260
260
|
// export async function GET() { return new Response(await seoMerchantFeedXml("/merchant-feed.xml"), {headers:{"content-type":"application/xml"}}) }
|
|
261
261
|
export async function seoMerchantFeedXml(path: string): Promise<string> {
|
|
262
262
|
// Валидный RSS-канал (title/link/description обязательны в RSS 2.0) с пустым списком товаров.
|
|
263
|
-
const FALLBACK = `<?xml version="1.0" encoding="UTF-8"?>\n<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">\n<channel>\n <title>Merchant feed</title>\n <link
|
|
263
|
+
const FALLBACK = `<?xml version="1.0" encoding="UTF-8"?>\n<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">\n<channel>\n <title>Merchant feed</title>\n <link></link>\n <description>Merchant feed temporarily unavailable</description>\n</channel>\n</rss>\n`;
|
|
264
264
|
if (!API || !SITE || !TOKEN) return FALLBACK;
|
|
265
265
|
try {
|
|
266
266
|
const r = await fetch(`${API}/api/seo/${SITE}${path}`, {
|
package/dist/client.js
CHANGED
|
@@ -262,7 +262,7 @@ async function seoSitemapXml(path) {
|
|
|
262
262
|
// export async function GET() { return new Response(await seoMerchantFeedXml("/merchant-feed.xml"), {headers:{"content-type":"application/xml"}}) }
|
|
263
263
|
async function seoMerchantFeedXml(path) {
|
|
264
264
|
// Валидный RSS-канал (title/link/description обязательны в RSS 2.0) с пустым списком товаров.
|
|
265
|
-
const FALLBACK = `<?xml version="1.0" encoding="UTF-8"?>\n<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">\n<channel>\n <title>Merchant feed</title>\n <link
|
|
265
|
+
const FALLBACK = `<?xml version="1.0" encoding="UTF-8"?>\n<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">\n<channel>\n <title>Merchant feed</title>\n <link></link>\n <description>Merchant feed temporarily unavailable</description>\n</channel>\n</rss>\n`;
|
|
266
266
|
if (!API || !SITE || !TOKEN)
|
|
267
267
|
return FALLBACK;
|
|
268
268
|
try {
|
package/package.json
CHANGED