@sonordev/site-kit 1.5.3 → 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.
@@ -36384,9 +36384,17 @@ async function syncPagesToPortal(apiUrl, apiKey, dryRun) {
36384
36384
  }
36385
36385
  const pages = discoverPages(appDir);
36386
36386
  spinner.succeed(`Found ${pages.length} pages`);
36387
+ const contentSpinner = ora("Extracting page content from build...").start();
36388
+ const enrichedCount = enrichPagesWithContent(pages);
36389
+ if (enrichedCount > 0) {
36390
+ contentSpinner.succeed(`Extracted content from ${enrichedCount}/${pages.length} pages`);
36391
+ } else {
36392
+ contentSpinner.warn("No build output found \u2014 run after `next build` for content extraction");
36393
+ }
36387
36394
  console.log(source_default.bold(" Pages to sync:"));
36388
36395
  for (const page of pages.slice(0, 10)) {
36389
- console.log(source_default.gray(` ${page.path} (priority: ${page.priority})`));
36396
+ const contentTag = page.content ? source_default.green(`${page.content.wordCount}w`) : source_default.gray("no content");
36397
+ console.log(source_default.gray(` ${page.path} (${contentTag})`));
36390
36398
  }
36391
36399
  if (pages.length > 10) {
36392
36400
  console.log(source_default.gray(` ... and ${pages.length - 10} more`));
@@ -36408,7 +36416,15 @@ async function syncPagesToPortal(apiUrl, apiKey, dryRun) {
36408
36416
  entries: pages.map((p) => ({
36409
36417
  path: p.path,
36410
36418
  priority: p.priority,
36411
- changefreq: p.changeFreq
36419
+ changefreq: p.changeFreq,
36420
+ // Build-time content extraction
36421
+ ...p.content ? {
36422
+ content_text: p.content.text,
36423
+ content_title: p.content.title,
36424
+ content_h1: p.content.h1,
36425
+ content_headings: p.content.headings,
36426
+ content_word_count: p.content.wordCount
36427
+ } : {}
36412
36428
  })),
36413
36429
  mode: "full-replace"
36414
36430
  })
@@ -36417,7 +36433,7 @@ async function syncPagesToPortal(apiUrl, apiKey, dryRun) {
36417
36433
  throw new Error(`HTTP ${response.status}: ${await response.text()}`);
36418
36434
  }
36419
36435
  const result = await response.json();
36420
- syncSpinner.succeed(`Synced pages: ${result.created || 0} created, ${result.updated || 0} updated`);
36436
+ syncSpinner.succeed(`Synced pages: ${result.created || 0} created, ${result.updated || 0} updated, ${result.content_updated || 0} with content`);
36421
36437
  } catch (error) {
36422
36438
  syncSpinner.fail(`Sync failed: ${error.message}`);
36423
36439
  }
@@ -36475,6 +36491,136 @@ function discoverPages(appDir, currentPath = "", pages = []) {
36475
36491
  }
36476
36492
  return pages;
36477
36493
  }
36494
+ function findNextBuildDir() {
36495
+ const cwd = process.cwd();
36496
+ const candidate = path4.join(cwd, ".next", "server", "app");
36497
+ return existsSync(candidate) ? candidate : null;
36498
+ }
36499
+ function extractPageContent(buildDir, pagePath) {
36500
+ const baseName = pagePath === "/" ? "index" : pagePath.replace(/^\//, "");
36501
+ const htmlCandidates = [
36502
+ path4.join(buildDir, `${baseName}.html`),
36503
+ path4.join(buildDir, baseName, "index.html")
36504
+ ];
36505
+ let html = null;
36506
+ for (const candidate of htmlCandidates) {
36507
+ if (existsSync(candidate)) {
36508
+ try {
36509
+ html = readFileSync(candidate, "utf-8");
36510
+ break;
36511
+ } catch {
36512
+ continue;
36513
+ }
36514
+ }
36515
+ }
36516
+ const rscCandidates = [
36517
+ path4.join(buildDir, `${baseName}.rsc`),
36518
+ path4.join(buildDir, baseName, "index.rsc")
36519
+ ];
36520
+ let rsc = null;
36521
+ for (const candidate of rscCandidates) {
36522
+ if (existsSync(candidate)) {
36523
+ try {
36524
+ rsc = readFileSync(candidate, "utf-8");
36525
+ break;
36526
+ } catch {
36527
+ continue;
36528
+ }
36529
+ }
36530
+ }
36531
+ if (!html && !rsc) return null;
36532
+ let title;
36533
+ let metaDescription;
36534
+ if (html) {
36535
+ const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
36536
+ title = titleMatch?.[1]?.trim();
36537
+ const descMatch = html.match(/<meta\s+name="description"\s+content="([^"]+)"/i);
36538
+ metaDescription = descMatch?.[1]?.trim();
36539
+ }
36540
+ if (rsc) {
36541
+ return parseRscContent(rsc, title, metaDescription);
36542
+ }
36543
+ if (html) {
36544
+ return parseHtmlContent(html);
36545
+ }
36546
+ return null;
36547
+ }
36548
+ function parseRscContent(rsc, title, metaDescription) {
36549
+ const textParts = [];
36550
+ const headings = [];
36551
+ const childrenRegex = /,"children":"([^"]+)"/g;
36552
+ let match;
36553
+ while ((match = childrenRegex.exec(rsc)) !== null) {
36554
+ const text2 = match[1].trim();
36555
+ if (!text2) continue;
36556
+ if (/^[A-Z]?\[/.test(text2)) continue;
36557
+ if (/^\//.test(text2) && !text2.includes(" ")) continue;
36558
+ if (/^\$L[0-9a-f]+$/i.test(text2)) continue;
36559
+ if (/^\$/.test(text2) && text2.length < 10) continue;
36560
+ textParts.push(text2);
36561
+ }
36562
+ const h1Regex = /\["\$","h1",[^,]*,\{[^}]*"children":"([^"]+)"/g;
36563
+ let h1;
36564
+ while ((match = h1Regex.exec(rsc)) !== null) {
36565
+ const text2 = match[1].trim();
36566
+ if (text2) {
36567
+ if (!h1) h1 = text2;
36568
+ headings.push(text2);
36569
+ }
36570
+ }
36571
+ const hRegex = /\["\$","h[2-6]",[^,]*,\{[^}]*"children":"([^"]+)"/g;
36572
+ while ((match = hRegex.exec(rsc)) !== null) {
36573
+ const text2 = match[1].trim();
36574
+ if (text2) headings.push(text2);
36575
+ }
36576
+ let text = textParts.join(" ").replace(/\s+/g, " ").trim();
36577
+ if (metaDescription && !text.includes(metaDescription)) {
36578
+ text = metaDescription + " \u2014 " + text;
36579
+ }
36580
+ if (text.length > 1e4) {
36581
+ text = text.substring(0, 1e4) + "...";
36582
+ }
36583
+ const wordCount = text.split(/\s+/).filter(Boolean).length;
36584
+ return { text, title, h1, headings, wordCount };
36585
+ }
36586
+ function parseHtmlContent(html) {
36587
+ const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
36588
+ const title = titleMatch?.[1]?.trim();
36589
+ 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, "");
36590
+ const h1Match = cleaned.match(/<h1[^>]*>([\s\S]*?)<\/h1>/i);
36591
+ const h1 = h1Match ? stripTags(h1Match[1]).trim() : void 0;
36592
+ const headingRegex = /<h[1-6][^>]*>([\s\S]*?)<\/h[1-6]>/gi;
36593
+ const headings = [];
36594
+ let match;
36595
+ while ((match = headingRegex.exec(cleaned)) !== null) {
36596
+ const text2 = stripTags(match[1]).trim();
36597
+ if (text2) headings.push(text2);
36598
+ }
36599
+ const mainMatch = cleaned.match(/<main[\s\S]*?>([\s\S]*?)<\/main>/i) || cleaned.match(/<article[\s\S]*?>([\s\S]*?)<\/article>/i);
36600
+ const contentHtml = mainMatch ? mainMatch[1] : cleaned;
36601
+ let text = stripTags(contentHtml).replace(/\s+/g, " ").trim();
36602
+ if (text.length > 1e4) {
36603
+ text = text.substring(0, 1e4) + "...";
36604
+ }
36605
+ const wordCount = text.split(/\s+/).filter(Boolean).length;
36606
+ return { text, title, h1, headings, wordCount };
36607
+ }
36608
+ function stripTags(html) {
36609
+ return html.replace(/<[^>]+>/g, " ").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&#\d+;/g, "");
36610
+ }
36611
+ function enrichPagesWithContent(pages) {
36612
+ const buildDir = findNextBuildDir();
36613
+ if (!buildDir) return 0;
36614
+ let enriched = 0;
36615
+ for (const page of pages) {
36616
+ const content = extractPageContent(buildDir, page.path);
36617
+ if (content && content.wordCount > 10) {
36618
+ page.content = content;
36619
+ enriched++;
36620
+ }
36621
+ }
36622
+ return enriched;
36623
+ }
36478
36624
  var BLOG_DIRS = ["app/blog", "content/blog", "posts", "src/content/blog"];
36479
36625
  var BLOG_EXTENSIONS = [".mdx", ".md"];
36480
36626
  function findBlogDir() {