@sonordev/site-kit 1.5.2 → 1.5.4
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/dist/cli/index.js +149 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +149 -3
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -36418,9 +36418,17 @@ async function syncPagesToPortal(apiUrl, apiKey, dryRun) {
|
|
|
36418
36418
|
}
|
|
36419
36419
|
const pages = discoverPages(appDir);
|
|
36420
36420
|
spinner.succeed(`Found ${pages.length} pages`);
|
|
36421
|
+
const contentSpinner = ora("Extracting page content from build...").start();
|
|
36422
|
+
const enrichedCount = enrichPagesWithContent(pages);
|
|
36423
|
+
if (enrichedCount > 0) {
|
|
36424
|
+
contentSpinner.succeed(`Extracted content from ${enrichedCount}/${pages.length} pages`);
|
|
36425
|
+
} else {
|
|
36426
|
+
contentSpinner.warn("No build output found \u2014 run after `next build` for content extraction");
|
|
36427
|
+
}
|
|
36421
36428
|
console.log(source_default.bold(" Pages to sync:"));
|
|
36422
36429
|
for (const page of pages.slice(0, 10)) {
|
|
36423
|
-
|
|
36430
|
+
const contentTag = page.content ? source_default.green(`${page.content.wordCount}w`) : source_default.gray("no content");
|
|
36431
|
+
console.log(source_default.gray(` ${page.path} (${contentTag})`));
|
|
36424
36432
|
}
|
|
36425
36433
|
if (pages.length > 10) {
|
|
36426
36434
|
console.log(source_default.gray(` ... and ${pages.length - 10} more`));
|
|
@@ -36442,7 +36450,15 @@ async function syncPagesToPortal(apiUrl, apiKey, dryRun) {
|
|
|
36442
36450
|
entries: pages.map((p) => ({
|
|
36443
36451
|
path: p.path,
|
|
36444
36452
|
priority: p.priority,
|
|
36445
|
-
changefreq: p.changeFreq
|
|
36453
|
+
changefreq: p.changeFreq,
|
|
36454
|
+
// Build-time content extraction
|
|
36455
|
+
...p.content ? {
|
|
36456
|
+
content_text: p.content.text,
|
|
36457
|
+
content_title: p.content.title,
|
|
36458
|
+
content_h1: p.content.h1,
|
|
36459
|
+
content_headings: p.content.headings,
|
|
36460
|
+
content_word_count: p.content.wordCount
|
|
36461
|
+
} : {}
|
|
36446
36462
|
})),
|
|
36447
36463
|
mode: "full-replace"
|
|
36448
36464
|
})
|
|
@@ -36451,7 +36467,7 @@ async function syncPagesToPortal(apiUrl, apiKey, dryRun) {
|
|
|
36451
36467
|
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
|
|
36452
36468
|
}
|
|
36453
36469
|
const result = await response.json();
|
|
36454
|
-
syncSpinner.succeed(`Synced pages: ${result.created || 0} created, ${result.updated || 0} updated`);
|
|
36470
|
+
syncSpinner.succeed(`Synced pages: ${result.created || 0} created, ${result.updated || 0} updated, ${result.content_updated || 0} with content`);
|
|
36455
36471
|
} catch (error) {
|
|
36456
36472
|
syncSpinner.fail(`Sync failed: ${error.message}`);
|
|
36457
36473
|
}
|
|
@@ -36509,6 +36525,136 @@ function discoverPages(appDir, currentPath = "", pages = []) {
|
|
|
36509
36525
|
}
|
|
36510
36526
|
return pages;
|
|
36511
36527
|
}
|
|
36528
|
+
function findNextBuildDir() {
|
|
36529
|
+
const cwd = process.cwd();
|
|
36530
|
+
const candidate = path4__default.default.join(cwd, ".next", "server", "app");
|
|
36531
|
+
return fs.existsSync(candidate) ? candidate : null;
|
|
36532
|
+
}
|
|
36533
|
+
function extractPageContent(buildDir, pagePath) {
|
|
36534
|
+
const baseName = pagePath === "/" ? "index" : pagePath.replace(/^\//, "");
|
|
36535
|
+
const htmlCandidates = [
|
|
36536
|
+
path4__default.default.join(buildDir, `${baseName}.html`),
|
|
36537
|
+
path4__default.default.join(buildDir, baseName, "index.html")
|
|
36538
|
+
];
|
|
36539
|
+
let html = null;
|
|
36540
|
+
for (const candidate of htmlCandidates) {
|
|
36541
|
+
if (fs.existsSync(candidate)) {
|
|
36542
|
+
try {
|
|
36543
|
+
html = fs.readFileSync(candidate, "utf-8");
|
|
36544
|
+
break;
|
|
36545
|
+
} catch {
|
|
36546
|
+
continue;
|
|
36547
|
+
}
|
|
36548
|
+
}
|
|
36549
|
+
}
|
|
36550
|
+
const rscCandidates = [
|
|
36551
|
+
path4__default.default.join(buildDir, `${baseName}.rsc`),
|
|
36552
|
+
path4__default.default.join(buildDir, baseName, "index.rsc")
|
|
36553
|
+
];
|
|
36554
|
+
let rsc = null;
|
|
36555
|
+
for (const candidate of rscCandidates) {
|
|
36556
|
+
if (fs.existsSync(candidate)) {
|
|
36557
|
+
try {
|
|
36558
|
+
rsc = fs.readFileSync(candidate, "utf-8");
|
|
36559
|
+
break;
|
|
36560
|
+
} catch {
|
|
36561
|
+
continue;
|
|
36562
|
+
}
|
|
36563
|
+
}
|
|
36564
|
+
}
|
|
36565
|
+
if (!html && !rsc) return null;
|
|
36566
|
+
let title;
|
|
36567
|
+
let metaDescription;
|
|
36568
|
+
if (html) {
|
|
36569
|
+
const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
|
|
36570
|
+
title = titleMatch?.[1]?.trim();
|
|
36571
|
+
const descMatch = html.match(/<meta\s+name="description"\s+content="([^"]+)"/i);
|
|
36572
|
+
metaDescription = descMatch?.[1]?.trim();
|
|
36573
|
+
}
|
|
36574
|
+
if (rsc) {
|
|
36575
|
+
return parseRscContent(rsc, title, metaDescription);
|
|
36576
|
+
}
|
|
36577
|
+
if (html) {
|
|
36578
|
+
return parseHtmlContent(html);
|
|
36579
|
+
}
|
|
36580
|
+
return null;
|
|
36581
|
+
}
|
|
36582
|
+
function parseRscContent(rsc, title, metaDescription) {
|
|
36583
|
+
const textParts = [];
|
|
36584
|
+
const headings = [];
|
|
36585
|
+
const childrenRegex = /,"children":"([^"]+)"/g;
|
|
36586
|
+
let match;
|
|
36587
|
+
while ((match = childrenRegex.exec(rsc)) !== null) {
|
|
36588
|
+
const text2 = match[1].trim();
|
|
36589
|
+
if (!text2) continue;
|
|
36590
|
+
if (/^[A-Z]?\[/.test(text2)) continue;
|
|
36591
|
+
if (/^\//.test(text2) && !text2.includes(" ")) continue;
|
|
36592
|
+
if (/^\$L[0-9a-f]+$/i.test(text2)) continue;
|
|
36593
|
+
if (/^\$/.test(text2) && text2.length < 10) continue;
|
|
36594
|
+
textParts.push(text2);
|
|
36595
|
+
}
|
|
36596
|
+
const h1Regex = /\["\$","h1",[^,]*,\{[^}]*"children":"([^"]+)"/g;
|
|
36597
|
+
let h1;
|
|
36598
|
+
while ((match = h1Regex.exec(rsc)) !== null) {
|
|
36599
|
+
const text2 = match[1].trim();
|
|
36600
|
+
if (text2) {
|
|
36601
|
+
if (!h1) h1 = text2;
|
|
36602
|
+
headings.push(text2);
|
|
36603
|
+
}
|
|
36604
|
+
}
|
|
36605
|
+
const hRegex = /\["\$","h[2-6]",[^,]*,\{[^}]*"children":"([^"]+)"/g;
|
|
36606
|
+
while ((match = hRegex.exec(rsc)) !== null) {
|
|
36607
|
+
const text2 = match[1].trim();
|
|
36608
|
+
if (text2) headings.push(text2);
|
|
36609
|
+
}
|
|
36610
|
+
let text = textParts.join(" ").replace(/\s+/g, " ").trim();
|
|
36611
|
+
if (metaDescription && !text.includes(metaDescription)) {
|
|
36612
|
+
text = metaDescription + " \u2014 " + text;
|
|
36613
|
+
}
|
|
36614
|
+
if (text.length > 1e4) {
|
|
36615
|
+
text = text.substring(0, 1e4) + "...";
|
|
36616
|
+
}
|
|
36617
|
+
const wordCount = text.split(/\s+/).filter(Boolean).length;
|
|
36618
|
+
return { text, title, h1, headings, wordCount };
|
|
36619
|
+
}
|
|
36620
|
+
function parseHtmlContent(html) {
|
|
36621
|
+
const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
|
|
36622
|
+
const title = titleMatch?.[1]?.trim();
|
|
36623
|
+
let cleaned = html.replace(/<script[\s\S]*?<\/script>/gi, "").replace(/<style[\s\S]*?<\/style>/gi, "").replace(/<svg[\s\S]*?<\/svg>/gi, "").replace(/<nav[\s\S]*?<\/nav>/gi, "").replace(/<footer[\s\S]*?<\/footer>/gi, "").replace(/<header[\s\S]*?<\/header>/gi, "").replace(/<[^>]+(?:hidden|display:\s*none|aria-hidden="true")[^>]*>[\s\S]*?<\/[^>]+>/gi, "");
|
|
36624
|
+
const h1Match = cleaned.match(/<h1[^>]*>([\s\S]*?)<\/h1>/i);
|
|
36625
|
+
const h1 = h1Match ? stripTags(h1Match[1]).trim() : void 0;
|
|
36626
|
+
const headingRegex = /<h[1-6][^>]*>([\s\S]*?)<\/h[1-6]>/gi;
|
|
36627
|
+
const headings = [];
|
|
36628
|
+
let match;
|
|
36629
|
+
while ((match = headingRegex.exec(cleaned)) !== null) {
|
|
36630
|
+
const text2 = stripTags(match[1]).trim();
|
|
36631
|
+
if (text2) headings.push(text2);
|
|
36632
|
+
}
|
|
36633
|
+
const mainMatch = cleaned.match(/<main[\s\S]*?>([\s\S]*?)<\/main>/i) || cleaned.match(/<article[\s\S]*?>([\s\S]*?)<\/article>/i);
|
|
36634
|
+
const contentHtml = mainMatch ? mainMatch[1] : cleaned;
|
|
36635
|
+
let text = stripTags(contentHtml).replace(/\s+/g, " ").trim();
|
|
36636
|
+
if (text.length > 1e4) {
|
|
36637
|
+
text = text.substring(0, 1e4) + "...";
|
|
36638
|
+
}
|
|
36639
|
+
const wordCount = text.split(/\s+/).filter(Boolean).length;
|
|
36640
|
+
return { text, title, h1, headings, wordCount };
|
|
36641
|
+
}
|
|
36642
|
+
function stripTags(html) {
|
|
36643
|
+
return html.replace(/<[^>]+>/g, " ").replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/&#\d+;/g, "");
|
|
36644
|
+
}
|
|
36645
|
+
function enrichPagesWithContent(pages) {
|
|
36646
|
+
const buildDir = findNextBuildDir();
|
|
36647
|
+
if (!buildDir) return 0;
|
|
36648
|
+
let enriched = 0;
|
|
36649
|
+
for (const page of pages) {
|
|
36650
|
+
const content = extractPageContent(buildDir, page.path);
|
|
36651
|
+
if (content && content.wordCount > 10) {
|
|
36652
|
+
page.content = content;
|
|
36653
|
+
enriched++;
|
|
36654
|
+
}
|
|
36655
|
+
}
|
|
36656
|
+
return enriched;
|
|
36657
|
+
}
|
|
36512
36658
|
var BLOG_DIRS = ["app/blog", "content/blog", "posts", "src/content/blog"];
|
|
36513
36659
|
var BLOG_EXTENSIONS = [".mdx", ".md"];
|
|
36514
36660
|
function findBlogDir() {
|