@bagelink/blox 1.15.230 → 1.15.232
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/{prerender-uiciCJgS.js → prerender-DnqZAE4x.js} +240 -13
- package/dist/{prerender-yrgljW5F.cjs → prerender-jcemLPiq.cjs} +234 -7
- package/dist/ssg/cli.cjs +18 -2
- package/dist/ssg/cli.mjs +18 -2
- package/dist/ssg/createSSREntry.d.ts.map +1 -1
- package/dist/ssg/index.cjs +39 -5
- package/dist/ssg/index.d.ts +2 -0
- package/dist/ssg/index.d.ts.map +1 -1
- package/dist/ssg/index.mjs +48 -14
- package/dist/ssg/llm-artifacts.d.ts +107 -0
- package/dist/ssg/llm-artifacts.d.ts.map +1 -0
- package/dist/ssg/prerender.d.ts +8 -1
- package/dist/ssg/prerender.d.ts.map +1 -1
- package/dist/ssg/render-resolved-page.d.ts +4 -0
- package/dist/ssg/render-resolved-page.d.ts.map +1 -1
- package/dist/ssg/seo.d.ts +24 -0
- package/dist/ssg/seo.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -329,16 +329,23 @@ function extractPrimaryContext(contexts) {
|
|
|
329
329
|
if (!contexts || typeof contexts !== "object") return empty;
|
|
330
330
|
const ctx = Object.values(contexts).find((c) => c != null);
|
|
331
331
|
if (!ctx) return empty;
|
|
332
|
-
const
|
|
332
|
+
const str2 = (key) => {
|
|
333
333
|
const v = ctx[key];
|
|
334
334
|
return typeof v === "string" && v.trim() ? v.trim() : null;
|
|
335
335
|
};
|
|
336
336
|
return {
|
|
337
|
-
title:
|
|
338
|
-
description:
|
|
339
|
-
image:
|
|
337
|
+
title: str2("meta_title") || str2("title"),
|
|
338
|
+
description: str2("meta_description") || str2("excerpt") || str2("description") || str2("blurb") || str2("summary"),
|
|
339
|
+
image: str2("og_image") || str2("cover_image_url") || str2("image_url") || str2("image")
|
|
340
340
|
};
|
|
341
341
|
}
|
|
342
|
+
function primaryContextEntry(contexts) {
|
|
343
|
+
if (!contexts || typeof contexts !== "object") return null;
|
|
344
|
+
for (const [key, ctx] of Object.entries(contexts)) {
|
|
345
|
+
if (ctx != null && typeof ctx === "object") return { key, ctx };
|
|
346
|
+
}
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
342
349
|
function esc(s) {
|
|
343
350
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
344
351
|
}
|
|
@@ -350,6 +357,196 @@ function absUrl(value) {
|
|
|
350
357
|
if (/^(https?:)?\/\//i.test(v) || v.startsWith("/")) return v;
|
|
351
358
|
return `${FILES_BASE_URL}/${v.replace(/^\/+/, "")}`;
|
|
352
359
|
}
|
|
360
|
+
function typeFromContextKey(key) {
|
|
361
|
+
const k = key.replace(/^\$/, "").toLowerCase();
|
|
362
|
+
if (/(post|article|blog|story|news)/.test(k)) return "Article";
|
|
363
|
+
if (/(product|listing|item|sku)/.test(k)) return "Product";
|
|
364
|
+
if (/(event|session|webinar)/.test(k)) return "Event";
|
|
365
|
+
return "WebPage";
|
|
366
|
+
}
|
|
367
|
+
function str(o, ...keys) {
|
|
368
|
+
for (const key of keys) {
|
|
369
|
+
const v = o[key];
|
|
370
|
+
if (typeof v === "string" && v.trim()) return v.trim();
|
|
371
|
+
}
|
|
372
|
+
return void 0;
|
|
373
|
+
}
|
|
374
|
+
function breadcrumbList(url, base, siteName) {
|
|
375
|
+
const segs = url.split("/").filter(Boolean);
|
|
376
|
+
const items = [
|
|
377
|
+
{ "@type": "ListItem", "position": 1, "name": siteName || "Home", "item": base || "/" }
|
|
378
|
+
];
|
|
379
|
+
let acc = "";
|
|
380
|
+
segs.forEach((seg, i) => {
|
|
381
|
+
acc += `/${seg}`;
|
|
382
|
+
items.push({
|
|
383
|
+
"@type": "ListItem",
|
|
384
|
+
"position": i + 2,
|
|
385
|
+
"name": decodeURIComponent(seg).replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
386
|
+
"item": base ? base + acc : acc
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
return { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": items };
|
|
390
|
+
}
|
|
391
|
+
function buildJsonLd(options) {
|
|
392
|
+
var _a;
|
|
393
|
+
const { url, page, website, contextKey, context, config } = options;
|
|
394
|
+
const seo = (website == null ? void 0 : website.seo) ?? {};
|
|
395
|
+
const base = (seo.canonical_base_url || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
396
|
+
const siteName = seo.site_name || void 0;
|
|
397
|
+
const pageUrl = base ? base + url : url;
|
|
398
|
+
const title = (page == null ? void 0 : page.meta_title) || (page == null ? void 0 : page.title) || str(context ?? {}, "meta_title", "title") || seo.default_meta_title;
|
|
399
|
+
const description = (page == null ? void 0 : page.meta_description) || str(context ?? {}, "meta_description", "excerpt", "description", "summary") || seo.default_meta_description;
|
|
400
|
+
const graphs = [];
|
|
401
|
+
const webPage = { "@context": "https://schema.org", "@type": "WebPage", "url": pageUrl };
|
|
402
|
+
if (title) webPage.name = title;
|
|
403
|
+
if (description) webPage.description = description;
|
|
404
|
+
if (siteName) webPage.isPartOf = { "@type": "WebSite", "name": siteName, "url": base || void 0 };
|
|
405
|
+
graphs.push(webPage);
|
|
406
|
+
if (url && url !== "/") graphs.push(breadcrumbList(url, base, siteName));
|
|
407
|
+
if (contextKey && context) {
|
|
408
|
+
const type = ((_a = config == null ? void 0 : config.typeMap) == null ? void 0 : _a[contextKey]) || typeFromContextKey(contextKey);
|
|
409
|
+
const entity = { "@context": "https://schema.org", "@type": type, "url": pageUrl };
|
|
410
|
+
const name = str(context, "title", "name", "meta_title");
|
|
411
|
+
const desc = str(context, "meta_description", "excerpt", "description", "summary", "blurb");
|
|
412
|
+
const image = str(context, "og_image", "cover_image_url", "image_url", "image");
|
|
413
|
+
if (name) entity.name = name;
|
|
414
|
+
if (desc) entity.description = desc;
|
|
415
|
+
if (image) entity.image = image;
|
|
416
|
+
if (type === "Article") {
|
|
417
|
+
if (siteName) entity.publisher = { "@type": "Organization", "name": siteName };
|
|
418
|
+
const date = str(context, "published_at", "created_at", "date");
|
|
419
|
+
if (date) entity.datePublished = date;
|
|
420
|
+
const upd = str(context, "updated_at", "modified_at");
|
|
421
|
+
if (upd) entity.dateModified = upd;
|
|
422
|
+
const author = str(context, "author", "author_name");
|
|
423
|
+
if (author) entity.author = { "@type": "Person", "name": author };
|
|
424
|
+
if (name) {
|
|
425
|
+
entity.headline = name;
|
|
426
|
+
delete entity.name;
|
|
427
|
+
}
|
|
428
|
+
} else if (type === "Product") {
|
|
429
|
+
const price = str(context, "price", "amount");
|
|
430
|
+
const currency = str(context, "currency", "currency_code") || "USD";
|
|
431
|
+
if (price) {
|
|
432
|
+
entity.offers = { "@type": "Offer", "price": price, "priceCurrency": currency, "url": pageUrl };
|
|
433
|
+
}
|
|
434
|
+
const sku = str(context, "sku", "id");
|
|
435
|
+
if (sku) entity.sku = sku;
|
|
436
|
+
} else if (type === "Event") {
|
|
437
|
+
const start = str(context, "start_at", "starts_at", "start_date", "date");
|
|
438
|
+
const end = str(context, "end_at", "ends_at", "end_date");
|
|
439
|
+
if (start) entity.startDate = start;
|
|
440
|
+
if (end) entity.endDate = end;
|
|
441
|
+
const loc = str(context, "location", "venue", "address");
|
|
442
|
+
if (loc) entity.location = { "@type": "Place", "name": loc };
|
|
443
|
+
}
|
|
444
|
+
graphs.push(entity);
|
|
445
|
+
}
|
|
446
|
+
return graphs.map((g) => `<script type="application/ld+json">${JSON.stringify(g)}${"<"}/script>`).join("\n");
|
|
447
|
+
}
|
|
448
|
+
function generateLlmsTxt(options) {
|
|
449
|
+
var _a;
|
|
450
|
+
const { website, pages, config } = options;
|
|
451
|
+
const seo = (website == null ? void 0 : website.seo) ?? {};
|
|
452
|
+
const base = (seo.canonical_base_url || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
453
|
+
const siteName = seo.site_name || (website == null ? void 0 : website.name) || "Website";
|
|
454
|
+
const summary = seo.default_meta_description;
|
|
455
|
+
const visible = pages.filter((p) => !isPathExcluded(p.url, config == null ? void 0 : config.excludePaths)).sort((a, b) => a.url.localeCompare(b.url));
|
|
456
|
+
const lines = [`# ${siteName}`, ""];
|
|
457
|
+
if (summary) lines.push(`> ${summary}`, "");
|
|
458
|
+
if (config == null ? void 0 : config.intro) lines.push(config.intro.trim(), "");
|
|
459
|
+
const abs = (u) => base ? base + u : u;
|
|
460
|
+
const link = (p) => {
|
|
461
|
+
const label = p.title || p.url;
|
|
462
|
+
const desc = p.description ? `: ${p.description}` : "";
|
|
463
|
+
return `- [${label}](${abs(p.url)})${desc}`;
|
|
464
|
+
};
|
|
465
|
+
const used = /* @__PURE__ */ new Set();
|
|
466
|
+
for (const section of (config == null ? void 0 : config.sections) ?? []) {
|
|
467
|
+
const inSection = visible.filter((p) => p.url.startsWith(section.prefix));
|
|
468
|
+
if (inSection.length === 0) continue;
|
|
469
|
+
lines.push(`## ${section.title}`, "");
|
|
470
|
+
for (const p of inSection) {
|
|
471
|
+
lines.push(link(p));
|
|
472
|
+
used.add(p.url);
|
|
473
|
+
}
|
|
474
|
+
lines.push("");
|
|
475
|
+
}
|
|
476
|
+
const rest = visible.filter((p) => !used.has(p.url));
|
|
477
|
+
if (rest.length > 0) {
|
|
478
|
+
lines.push(((_a = config == null ? void 0 : config.sections) == null ? void 0 : _a.length) ? "## Pages" : "## Pages", "");
|
|
479
|
+
for (const p of rest) lines.push(link(p));
|
|
480
|
+
lines.push("");
|
|
481
|
+
}
|
|
482
|
+
return `${lines.join("\n").trimEnd()}
|
|
483
|
+
`;
|
|
484
|
+
}
|
|
485
|
+
function generateLlmsFullTxt(options) {
|
|
486
|
+
const { website, pages, config } = options;
|
|
487
|
+
const seo = (website == null ? void 0 : website.seo) ?? {};
|
|
488
|
+
const base = (seo.canonical_base_url || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
489
|
+
const siteName = seo.site_name || (website == null ? void 0 : website.name) || "Website";
|
|
490
|
+
const visible = pages.filter((p) => !isPathExcluded(p.url, config == null ? void 0 : config.excludePaths)).filter((p) => p.text && p.text.trim()).sort((a, b) => a.url.localeCompare(b.url));
|
|
491
|
+
const blocks = [`# ${siteName}`, ""];
|
|
492
|
+
for (const p of visible) {
|
|
493
|
+
const abs = base ? base + p.url : p.url;
|
|
494
|
+
blocks.push(`## ${p.title || p.url}`, "", `Source: ${abs}`, "");
|
|
495
|
+
if (p.description) blocks.push(`> ${p.description}`, "");
|
|
496
|
+
blocks.push(p.text.trim(), "", "---", "");
|
|
497
|
+
}
|
|
498
|
+
return `${blocks.join("\n").trimEnd()}
|
|
499
|
+
`;
|
|
500
|
+
}
|
|
501
|
+
function extractPageText(html) {
|
|
502
|
+
if (!html) return "";
|
|
503
|
+
let s = html;
|
|
504
|
+
s = s.replace(/<(script|style|noscript|svg|template)\b[^>]*>[\s\S]*?<\/\1>/gi, " ");
|
|
505
|
+
s = s.replace(/<(nav|header|footer)\b[^>]*>[\s\S]*?<\/\1>/gi, " ");
|
|
506
|
+
s = s.replace(/<h1\b[^>]*>/gi, "\n\n# ").replace(/<h2\b[^>]*>/gi, "\n\n## ").replace(/<h3\b[^>]*>/gi, "\n\n### ").replace(/<(h4|h5|h6)\b[^>]*>/gi, "\n\n#### ");
|
|
507
|
+
s = s.replace(/<li\b[^>]*>/gi, "\n- ");
|
|
508
|
+
s = s.replace(/<(\/p|\/div|\/section|\/article|br\s*\/?|\/li|\/h[1-6])>/gi, "\n");
|
|
509
|
+
s = s.replace(/<[^>]+>/g, " ");
|
|
510
|
+
s = s.replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
|
|
511
|
+
s = s.split("\n").map((l) => l.replace(/[ \t]+/g, " ").trim()).join("\n");
|
|
512
|
+
s = s.replace(/\n{3,}/g, "\n\n").trim();
|
|
513
|
+
return s;
|
|
514
|
+
}
|
|
515
|
+
function isPathExcluded(path2, patterns) {
|
|
516
|
+
if (!patterns || patterns.length === 0) return false;
|
|
517
|
+
return patterns.some((p) => {
|
|
518
|
+
if (p.endsWith("*")) return path2.startsWith(p.slice(0, -1));
|
|
519
|
+
return path2 === p;
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
async function mergeLlmParts(options) {
|
|
523
|
+
const fs2 = await import("node:fs/promises");
|
|
524
|
+
const path2 = await import("node:path");
|
|
525
|
+
const byUrl = /* @__PURE__ */ new Map();
|
|
526
|
+
for (const file of options.partFiles) {
|
|
527
|
+
try {
|
|
528
|
+
const raw = await fs2.readFile(file, "utf8");
|
|
529
|
+
const arr = JSON.parse(raw);
|
|
530
|
+
for (const e of arr) if (e == null ? void 0 : e.url) byUrl.set(e.url, e);
|
|
531
|
+
} catch {
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
const pages = [...byUrl.values()];
|
|
535
|
+
const { website, config } = options;
|
|
536
|
+
const llmsTxt = generateLlmsTxt({ website, pages, config });
|
|
537
|
+
await fs2.writeFile(path2.join(options.outDir, "llms.txt"), llmsTxt, "utf8");
|
|
538
|
+
if ((config == null ? void 0 : config.fullText) !== false) {
|
|
539
|
+
const full = generateLlmsFullTxt({ website, pages, config });
|
|
540
|
+
await fs2.writeFile(path2.join(options.outDir, "llms-full.txt"), full, "utf8");
|
|
541
|
+
}
|
|
542
|
+
for (const file of options.partFiles) {
|
|
543
|
+
try {
|
|
544
|
+
await fs2.unlink(file);
|
|
545
|
+
} catch {
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
return { pages: pages.length };
|
|
549
|
+
}
|
|
353
550
|
async function prerender({
|
|
354
551
|
root = process.cwd(),
|
|
355
552
|
clientOutDir = "dist/client",
|
|
@@ -376,7 +573,8 @@ async function prerender({
|
|
|
376
573
|
website = null,
|
|
377
574
|
websiteId = "",
|
|
378
575
|
redirects = [],
|
|
379
|
-
collections = {}
|
|
576
|
+
collections = {},
|
|
577
|
+
llm = {}
|
|
380
578
|
} = {}) {
|
|
381
579
|
var _a, _b;
|
|
382
580
|
const absRoot = path.resolve(root);
|
|
@@ -411,6 +609,8 @@ async function prerender({
|
|
|
411
609
|
const rendered = [];
|
|
412
610
|
const noindexPaths = /* @__PURE__ */ new Set();
|
|
413
611
|
const lastmod = {};
|
|
612
|
+
const llmPages = [];
|
|
613
|
+
const llmEnabled = llm.enabled !== false;
|
|
414
614
|
const failures = [];
|
|
415
615
|
const resolveCache = /* @__PURE__ */ new Map();
|
|
416
616
|
const prefetch = serverMod.prefetchResolve;
|
|
@@ -438,14 +638,16 @@ async function prerender({
|
|
|
438
638
|
html,
|
|
439
639
|
head = "",
|
|
440
640
|
htmlAttrs = "",
|
|
441
|
-
lastmod: pageLastmod
|
|
641
|
+
lastmod: pageLastmod,
|
|
642
|
+
llm: pageLlm
|
|
442
643
|
} = await serverMod.render(urlPath, {
|
|
443
644
|
manifest,
|
|
444
645
|
template,
|
|
445
646
|
website,
|
|
446
647
|
websiteId,
|
|
447
648
|
collections,
|
|
448
|
-
resolveCache
|
|
649
|
+
resolveCache,
|
|
650
|
+
llm
|
|
449
651
|
});
|
|
450
652
|
const outHtml = injectIntoTemplate(template, head, html, fontPreloads, htmlAttrs);
|
|
451
653
|
const outfile = outFilePath(absClient, urlPath, mode);
|
|
@@ -453,6 +655,7 @@ async function prerender({
|
|
|
453
655
|
await fs.writeFile(outfile, outHtml, "utf8");
|
|
454
656
|
rendered.push(urlPath);
|
|
455
657
|
if (pageLastmod) lastmod[urlPath] = pageLastmod;
|
|
658
|
+
if (llmEnabled && pageLlm) llmPages.push(pageLlm);
|
|
456
659
|
if (/<meta[^>]+name=["']robots["'][^>]*noindex/i.test(head)) {
|
|
457
660
|
noindexPaths.add(urlPath);
|
|
458
661
|
}
|
|
@@ -518,6 +721,24 @@ async function prerender({
|
|
|
518
721
|
await fs.writeFile(redirectsPath, redirectsContent + existing, "utf8");
|
|
519
722
|
console.log(` Generated _redirects (${redirects.length} rules)`);
|
|
520
723
|
}
|
|
724
|
+
if (llmEnabled && llm.writeIndex !== false && llmPages.length > 0) {
|
|
725
|
+
const indexable = llmPages.filter((p) => !noindexPaths.has(p.url));
|
|
726
|
+
const llmsTxt = generateLlmsTxt({ website, pages: indexable, config: llm });
|
|
727
|
+
await fs.writeFile(path.join(absClient, "llms.txt"), llmsTxt, "utf8");
|
|
728
|
+
console.log(` Generated llms.txt (${indexable.length} pages)`);
|
|
729
|
+
if (llm.fullText !== false) {
|
|
730
|
+
const full = generateLlmsFullTxt({ website, pages: indexable, config: llm });
|
|
731
|
+
await fs.writeFile(path.join(absClient, "llms-full.txt"), full, "utf8");
|
|
732
|
+
console.log(" Generated llms-full.txt");
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
if (llmEnabled && llm.partsFile && llmPages.length > 0) {
|
|
737
|
+
const indexable = llmPages.filter((p) => !noindexPaths.has(p.url));
|
|
738
|
+
const partPath = path.resolve(absRoot, llm.partsFile);
|
|
739
|
+
await fs.mkdir(path.dirname(partPath), { recursive: true });
|
|
740
|
+
await fs.writeFile(partPath, JSON.stringify(indexable), "utf8");
|
|
741
|
+
console.log(` Wrote ${indexable.length} llm page extract(s) → ${llm.partsFile}`);
|
|
521
742
|
}
|
|
522
743
|
return {
|
|
523
744
|
rendered,
|
|
@@ -653,12 +874,18 @@ function discoverInternalLinks(html) {
|
|
|
653
874
|
export {
|
|
654
875
|
prerender as a,
|
|
655
876
|
buildPageHead as b,
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
877
|
+
primaryContextEntry as c,
|
|
878
|
+
buildJsonLd as d,
|
|
879
|
+
extractPageText as e,
|
|
659
880
|
fetchCmsSiteData as f,
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
881
|
+
buildSiteHead as g,
|
|
882
|
+
fetchCmsPrerenderPaths as h,
|
|
883
|
+
generateLlmsFullTxt as i,
|
|
884
|
+
generateLlmsTxt as j,
|
|
885
|
+
generateNetlifyRedirects as k,
|
|
886
|
+
generateRobotsTxt as l,
|
|
887
|
+
generateSitemapXml as m,
|
|
888
|
+
getSiteIconFlags as n,
|
|
889
|
+
mergeLlmParts as o,
|
|
663
890
|
polyfillBloxSsgGlobals as p
|
|
664
891
|
};
|
|
@@ -352,16 +352,23 @@ function extractPrimaryContext(contexts) {
|
|
|
352
352
|
if (!contexts || typeof contexts !== "object") return empty;
|
|
353
353
|
const ctx = Object.values(contexts).find((c) => c != null);
|
|
354
354
|
if (!ctx) return empty;
|
|
355
|
-
const
|
|
355
|
+
const str2 = (key) => {
|
|
356
356
|
const v = ctx[key];
|
|
357
357
|
return typeof v === "string" && v.trim() ? v.trim() : null;
|
|
358
358
|
};
|
|
359
359
|
return {
|
|
360
|
-
title:
|
|
361
|
-
description:
|
|
362
|
-
image:
|
|
360
|
+
title: str2("meta_title") || str2("title"),
|
|
361
|
+
description: str2("meta_description") || str2("excerpt") || str2("description") || str2("blurb") || str2("summary"),
|
|
362
|
+
image: str2("og_image") || str2("cover_image_url") || str2("image_url") || str2("image")
|
|
363
363
|
};
|
|
364
364
|
}
|
|
365
|
+
function primaryContextEntry(contexts) {
|
|
366
|
+
if (!contexts || typeof contexts !== "object") return null;
|
|
367
|
+
for (const [key, ctx] of Object.entries(contexts)) {
|
|
368
|
+
if (ctx != null && typeof ctx === "object") return { key, ctx };
|
|
369
|
+
}
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
365
372
|
function esc(s) {
|
|
366
373
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
367
374
|
}
|
|
@@ -373,6 +380,196 @@ function absUrl(value) {
|
|
|
373
380
|
if (/^(https?:)?\/\//i.test(v) || v.startsWith("/")) return v;
|
|
374
381
|
return `${FILES_BASE_URL}/${v.replace(/^\/+/, "")}`;
|
|
375
382
|
}
|
|
383
|
+
function typeFromContextKey(key) {
|
|
384
|
+
const k = key.replace(/^\$/, "").toLowerCase();
|
|
385
|
+
if (/(post|article|blog|story|news)/.test(k)) return "Article";
|
|
386
|
+
if (/(product|listing|item|sku)/.test(k)) return "Product";
|
|
387
|
+
if (/(event|session|webinar)/.test(k)) return "Event";
|
|
388
|
+
return "WebPage";
|
|
389
|
+
}
|
|
390
|
+
function str(o, ...keys) {
|
|
391
|
+
for (const key of keys) {
|
|
392
|
+
const v = o[key];
|
|
393
|
+
if (typeof v === "string" && v.trim()) return v.trim();
|
|
394
|
+
}
|
|
395
|
+
return void 0;
|
|
396
|
+
}
|
|
397
|
+
function breadcrumbList(url, base, siteName) {
|
|
398
|
+
const segs = url.split("/").filter(Boolean);
|
|
399
|
+
const items = [
|
|
400
|
+
{ "@type": "ListItem", "position": 1, "name": siteName || "Home", "item": base || "/" }
|
|
401
|
+
];
|
|
402
|
+
let acc = "";
|
|
403
|
+
segs.forEach((seg, i) => {
|
|
404
|
+
acc += `/${seg}`;
|
|
405
|
+
items.push({
|
|
406
|
+
"@type": "ListItem",
|
|
407
|
+
"position": i + 2,
|
|
408
|
+
"name": decodeURIComponent(seg).replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
409
|
+
"item": base ? base + acc : acc
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
return { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": items };
|
|
413
|
+
}
|
|
414
|
+
function buildJsonLd(options) {
|
|
415
|
+
var _a;
|
|
416
|
+
const { url, page, website, contextKey, context, config } = options;
|
|
417
|
+
const seo = (website == null ? void 0 : website.seo) ?? {};
|
|
418
|
+
const base = (seo.canonical_base_url || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
419
|
+
const siteName = seo.site_name || void 0;
|
|
420
|
+
const pageUrl = base ? base + url : url;
|
|
421
|
+
const title = (page == null ? void 0 : page.meta_title) || (page == null ? void 0 : page.title) || str(context ?? {}, "meta_title", "title") || seo.default_meta_title;
|
|
422
|
+
const description = (page == null ? void 0 : page.meta_description) || str(context ?? {}, "meta_description", "excerpt", "description", "summary") || seo.default_meta_description;
|
|
423
|
+
const graphs = [];
|
|
424
|
+
const webPage = { "@context": "https://schema.org", "@type": "WebPage", "url": pageUrl };
|
|
425
|
+
if (title) webPage.name = title;
|
|
426
|
+
if (description) webPage.description = description;
|
|
427
|
+
if (siteName) webPage.isPartOf = { "@type": "WebSite", "name": siteName, "url": base || void 0 };
|
|
428
|
+
graphs.push(webPage);
|
|
429
|
+
if (url && url !== "/") graphs.push(breadcrumbList(url, base, siteName));
|
|
430
|
+
if (contextKey && context) {
|
|
431
|
+
const type = ((_a = config == null ? void 0 : config.typeMap) == null ? void 0 : _a[contextKey]) || typeFromContextKey(contextKey);
|
|
432
|
+
const entity = { "@context": "https://schema.org", "@type": type, "url": pageUrl };
|
|
433
|
+
const name = str(context, "title", "name", "meta_title");
|
|
434
|
+
const desc = str(context, "meta_description", "excerpt", "description", "summary", "blurb");
|
|
435
|
+
const image = str(context, "og_image", "cover_image_url", "image_url", "image");
|
|
436
|
+
if (name) entity.name = name;
|
|
437
|
+
if (desc) entity.description = desc;
|
|
438
|
+
if (image) entity.image = image;
|
|
439
|
+
if (type === "Article") {
|
|
440
|
+
if (siteName) entity.publisher = { "@type": "Organization", "name": siteName };
|
|
441
|
+
const date = str(context, "published_at", "created_at", "date");
|
|
442
|
+
if (date) entity.datePublished = date;
|
|
443
|
+
const upd = str(context, "updated_at", "modified_at");
|
|
444
|
+
if (upd) entity.dateModified = upd;
|
|
445
|
+
const author = str(context, "author", "author_name");
|
|
446
|
+
if (author) entity.author = { "@type": "Person", "name": author };
|
|
447
|
+
if (name) {
|
|
448
|
+
entity.headline = name;
|
|
449
|
+
delete entity.name;
|
|
450
|
+
}
|
|
451
|
+
} else if (type === "Product") {
|
|
452
|
+
const price = str(context, "price", "amount");
|
|
453
|
+
const currency = str(context, "currency", "currency_code") || "USD";
|
|
454
|
+
if (price) {
|
|
455
|
+
entity.offers = { "@type": "Offer", "price": price, "priceCurrency": currency, "url": pageUrl };
|
|
456
|
+
}
|
|
457
|
+
const sku = str(context, "sku", "id");
|
|
458
|
+
if (sku) entity.sku = sku;
|
|
459
|
+
} else if (type === "Event") {
|
|
460
|
+
const start = str(context, "start_at", "starts_at", "start_date", "date");
|
|
461
|
+
const end = str(context, "end_at", "ends_at", "end_date");
|
|
462
|
+
if (start) entity.startDate = start;
|
|
463
|
+
if (end) entity.endDate = end;
|
|
464
|
+
const loc = str(context, "location", "venue", "address");
|
|
465
|
+
if (loc) entity.location = { "@type": "Place", "name": loc };
|
|
466
|
+
}
|
|
467
|
+
graphs.push(entity);
|
|
468
|
+
}
|
|
469
|
+
return graphs.map((g) => `<script type="application/ld+json">${JSON.stringify(g)}${"<"}/script>`).join("\n");
|
|
470
|
+
}
|
|
471
|
+
function generateLlmsTxt(options) {
|
|
472
|
+
var _a;
|
|
473
|
+
const { website, pages, config } = options;
|
|
474
|
+
const seo = (website == null ? void 0 : website.seo) ?? {};
|
|
475
|
+
const base = (seo.canonical_base_url || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
476
|
+
const siteName = seo.site_name || (website == null ? void 0 : website.name) || "Website";
|
|
477
|
+
const summary = seo.default_meta_description;
|
|
478
|
+
const visible = pages.filter((p) => !isPathExcluded(p.url, config == null ? void 0 : config.excludePaths)).sort((a, b) => a.url.localeCompare(b.url));
|
|
479
|
+
const lines = [`# ${siteName}`, ""];
|
|
480
|
+
if (summary) lines.push(`> ${summary}`, "");
|
|
481
|
+
if (config == null ? void 0 : config.intro) lines.push(config.intro.trim(), "");
|
|
482
|
+
const abs = (u) => base ? base + u : u;
|
|
483
|
+
const link = (p) => {
|
|
484
|
+
const label = p.title || p.url;
|
|
485
|
+
const desc = p.description ? `: ${p.description}` : "";
|
|
486
|
+
return `- [${label}](${abs(p.url)})${desc}`;
|
|
487
|
+
};
|
|
488
|
+
const used = /* @__PURE__ */ new Set();
|
|
489
|
+
for (const section of (config == null ? void 0 : config.sections) ?? []) {
|
|
490
|
+
const inSection = visible.filter((p) => p.url.startsWith(section.prefix));
|
|
491
|
+
if (inSection.length === 0) continue;
|
|
492
|
+
lines.push(`## ${section.title}`, "");
|
|
493
|
+
for (const p of inSection) {
|
|
494
|
+
lines.push(link(p));
|
|
495
|
+
used.add(p.url);
|
|
496
|
+
}
|
|
497
|
+
lines.push("");
|
|
498
|
+
}
|
|
499
|
+
const rest = visible.filter((p) => !used.has(p.url));
|
|
500
|
+
if (rest.length > 0) {
|
|
501
|
+
lines.push(((_a = config == null ? void 0 : config.sections) == null ? void 0 : _a.length) ? "## Pages" : "## Pages", "");
|
|
502
|
+
for (const p of rest) lines.push(link(p));
|
|
503
|
+
lines.push("");
|
|
504
|
+
}
|
|
505
|
+
return `${lines.join("\n").trimEnd()}
|
|
506
|
+
`;
|
|
507
|
+
}
|
|
508
|
+
function generateLlmsFullTxt(options) {
|
|
509
|
+
const { website, pages, config } = options;
|
|
510
|
+
const seo = (website == null ? void 0 : website.seo) ?? {};
|
|
511
|
+
const base = (seo.canonical_base_url || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
512
|
+
const siteName = seo.site_name || (website == null ? void 0 : website.name) || "Website";
|
|
513
|
+
const visible = pages.filter((p) => !isPathExcluded(p.url, config == null ? void 0 : config.excludePaths)).filter((p) => p.text && p.text.trim()).sort((a, b) => a.url.localeCompare(b.url));
|
|
514
|
+
const blocks = [`# ${siteName}`, ""];
|
|
515
|
+
for (const p of visible) {
|
|
516
|
+
const abs = base ? base + p.url : p.url;
|
|
517
|
+
blocks.push(`## ${p.title || p.url}`, "", `Source: ${abs}`, "");
|
|
518
|
+
if (p.description) blocks.push(`> ${p.description}`, "");
|
|
519
|
+
blocks.push(p.text.trim(), "", "---", "");
|
|
520
|
+
}
|
|
521
|
+
return `${blocks.join("\n").trimEnd()}
|
|
522
|
+
`;
|
|
523
|
+
}
|
|
524
|
+
function extractPageText(html) {
|
|
525
|
+
if (!html) return "";
|
|
526
|
+
let s = html;
|
|
527
|
+
s = s.replace(/<(script|style|noscript|svg|template)\b[^>]*>[\s\S]*?<\/\1>/gi, " ");
|
|
528
|
+
s = s.replace(/<(nav|header|footer)\b[^>]*>[\s\S]*?<\/\1>/gi, " ");
|
|
529
|
+
s = s.replace(/<h1\b[^>]*>/gi, "\n\n# ").replace(/<h2\b[^>]*>/gi, "\n\n## ").replace(/<h3\b[^>]*>/gi, "\n\n### ").replace(/<(h4|h5|h6)\b[^>]*>/gi, "\n\n#### ");
|
|
530
|
+
s = s.replace(/<li\b[^>]*>/gi, "\n- ");
|
|
531
|
+
s = s.replace(/<(\/p|\/div|\/section|\/article|br\s*\/?|\/li|\/h[1-6])>/gi, "\n");
|
|
532
|
+
s = s.replace(/<[^>]+>/g, " ");
|
|
533
|
+
s = s.replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
|
|
534
|
+
s = s.split("\n").map((l) => l.replace(/[ \t]+/g, " ").trim()).join("\n");
|
|
535
|
+
s = s.replace(/\n{3,}/g, "\n\n").trim();
|
|
536
|
+
return s;
|
|
537
|
+
}
|
|
538
|
+
function isPathExcluded(path2, patterns) {
|
|
539
|
+
if (!patterns || patterns.length === 0) return false;
|
|
540
|
+
return patterns.some((p) => {
|
|
541
|
+
if (p.endsWith("*")) return path2.startsWith(p.slice(0, -1));
|
|
542
|
+
return path2 === p;
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
async function mergeLlmParts(options) {
|
|
546
|
+
const fs2 = await import("node:fs/promises");
|
|
547
|
+
const path2 = await import("node:path");
|
|
548
|
+
const byUrl = /* @__PURE__ */ new Map();
|
|
549
|
+
for (const file of options.partFiles) {
|
|
550
|
+
try {
|
|
551
|
+
const raw = await fs2.readFile(file, "utf8");
|
|
552
|
+
const arr = JSON.parse(raw);
|
|
553
|
+
for (const e of arr) if (e == null ? void 0 : e.url) byUrl.set(e.url, e);
|
|
554
|
+
} catch {
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
const pages = [...byUrl.values()];
|
|
558
|
+
const { website, config } = options;
|
|
559
|
+
const llmsTxt = generateLlmsTxt({ website, pages, config });
|
|
560
|
+
await fs2.writeFile(path2.join(options.outDir, "llms.txt"), llmsTxt, "utf8");
|
|
561
|
+
if ((config == null ? void 0 : config.fullText) !== false) {
|
|
562
|
+
const full = generateLlmsFullTxt({ website, pages, config });
|
|
563
|
+
await fs2.writeFile(path2.join(options.outDir, "llms-full.txt"), full, "utf8");
|
|
564
|
+
}
|
|
565
|
+
for (const file of options.partFiles) {
|
|
566
|
+
try {
|
|
567
|
+
await fs2.unlink(file);
|
|
568
|
+
} catch {
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return { pages: pages.length };
|
|
572
|
+
}
|
|
376
573
|
async function prerender({
|
|
377
574
|
root = process.cwd(),
|
|
378
575
|
clientOutDir = "dist/client",
|
|
@@ -399,7 +596,8 @@ async function prerender({
|
|
|
399
596
|
website = null,
|
|
400
597
|
websiteId = "",
|
|
401
598
|
redirects = [],
|
|
402
|
-
collections = {}
|
|
599
|
+
collections = {},
|
|
600
|
+
llm = {}
|
|
403
601
|
} = {}) {
|
|
404
602
|
var _a, _b;
|
|
405
603
|
const absRoot = path.resolve(root);
|
|
@@ -434,6 +632,8 @@ async function prerender({
|
|
|
434
632
|
const rendered = [];
|
|
435
633
|
const noindexPaths = /* @__PURE__ */ new Set();
|
|
436
634
|
const lastmod = {};
|
|
635
|
+
const llmPages = [];
|
|
636
|
+
const llmEnabled = llm.enabled !== false;
|
|
437
637
|
const failures = [];
|
|
438
638
|
const resolveCache = /* @__PURE__ */ new Map();
|
|
439
639
|
const prefetch = serverMod.prefetchResolve;
|
|
@@ -461,14 +661,16 @@ async function prerender({
|
|
|
461
661
|
html,
|
|
462
662
|
head = "",
|
|
463
663
|
htmlAttrs = "",
|
|
464
|
-
lastmod: pageLastmod
|
|
664
|
+
lastmod: pageLastmod,
|
|
665
|
+
llm: pageLlm
|
|
465
666
|
} = await serverMod.render(urlPath, {
|
|
466
667
|
manifest,
|
|
467
668
|
template,
|
|
468
669
|
website,
|
|
469
670
|
websiteId,
|
|
470
671
|
collections,
|
|
471
|
-
resolveCache
|
|
672
|
+
resolveCache,
|
|
673
|
+
llm
|
|
472
674
|
});
|
|
473
675
|
const outHtml = injectIntoTemplate(template, head, html, fontPreloads, htmlAttrs);
|
|
474
676
|
const outfile = outFilePath(absClient, urlPath, mode);
|
|
@@ -476,6 +678,7 @@ async function prerender({
|
|
|
476
678
|
await fs.writeFile(outfile, outHtml, "utf8");
|
|
477
679
|
rendered.push(urlPath);
|
|
478
680
|
if (pageLastmod) lastmod[urlPath] = pageLastmod;
|
|
681
|
+
if (llmEnabled && pageLlm) llmPages.push(pageLlm);
|
|
479
682
|
if (/<meta[^>]+name=["']robots["'][^>]*noindex/i.test(head)) {
|
|
480
683
|
noindexPaths.add(urlPath);
|
|
481
684
|
}
|
|
@@ -541,6 +744,24 @@ async function prerender({
|
|
|
541
744
|
await fs.writeFile(redirectsPath, redirectsContent + existing, "utf8");
|
|
542
745
|
console.log(` Generated _redirects (${redirects.length} rules)`);
|
|
543
746
|
}
|
|
747
|
+
if (llmEnabled && llm.writeIndex !== false && llmPages.length > 0) {
|
|
748
|
+
const indexable = llmPages.filter((p) => !noindexPaths.has(p.url));
|
|
749
|
+
const llmsTxt = generateLlmsTxt({ website, pages: indexable, config: llm });
|
|
750
|
+
await fs.writeFile(path.join(absClient, "llms.txt"), llmsTxt, "utf8");
|
|
751
|
+
console.log(` Generated llms.txt (${indexable.length} pages)`);
|
|
752
|
+
if (llm.fullText !== false) {
|
|
753
|
+
const full = generateLlmsFullTxt({ website, pages: indexable, config: llm });
|
|
754
|
+
await fs.writeFile(path.join(absClient, "llms-full.txt"), full, "utf8");
|
|
755
|
+
console.log(" Generated llms-full.txt");
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
if (llmEnabled && llm.partsFile && llmPages.length > 0) {
|
|
760
|
+
const indexable = llmPages.filter((p) => !noindexPaths.has(p.url));
|
|
761
|
+
const partPath = path.resolve(absRoot, llm.partsFile);
|
|
762
|
+
await fs.mkdir(path.dirname(partPath), { recursive: true });
|
|
763
|
+
await fs.writeFile(partPath, JSON.stringify(indexable), "utf8");
|
|
764
|
+
console.log(` Wrote ${indexable.length} llm page extract(s) → ${llm.partsFile}`);
|
|
544
765
|
}
|
|
545
766
|
return {
|
|
546
767
|
rendered,
|
|
@@ -673,13 +894,19 @@ function discoverInternalLinks(html) {
|
|
|
673
894
|
}
|
|
674
895
|
return [...out];
|
|
675
896
|
}
|
|
897
|
+
exports.buildJsonLd = buildJsonLd;
|
|
676
898
|
exports.buildPageHead = buildPageHead;
|
|
677
899
|
exports.buildSiteHead = buildSiteHead;
|
|
900
|
+
exports.extractPageText = extractPageText;
|
|
678
901
|
exports.fetchCmsPrerenderPaths = fetchCmsPrerenderPaths;
|
|
679
902
|
exports.fetchCmsSiteData = fetchCmsSiteData;
|
|
903
|
+
exports.generateLlmsFullTxt = generateLlmsFullTxt;
|
|
904
|
+
exports.generateLlmsTxt = generateLlmsTxt;
|
|
680
905
|
exports.generateNetlifyRedirects = generateNetlifyRedirects;
|
|
681
906
|
exports.generateRobotsTxt = generateRobotsTxt;
|
|
682
907
|
exports.generateSitemapXml = generateSitemapXml;
|
|
683
908
|
exports.getSiteIconFlags = getSiteIconFlags;
|
|
909
|
+
exports.mergeLlmParts = mergeLlmParts;
|
|
684
910
|
exports.polyfillBloxSsgGlobals = polyfillBloxSsgGlobals;
|
|
685
911
|
exports.prerender = prerender;
|
|
912
|
+
exports.primaryContextEntry = primaryContextEntry;
|
package/dist/ssg/cli.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
"use strict";
|
|
3
3
|
const process = require("node:process");
|
|
4
|
-
const prerender = require("../prerender-
|
|
4
|
+
const prerender = require("../prerender-jcemLPiq.cjs");
|
|
5
5
|
function installFetchTimeout() {
|
|
6
6
|
const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
|
|
7
7
|
const original = globalThis.fetch;
|
|
@@ -47,6 +47,7 @@ async function main() {
|
|
|
47
47
|
let mode = "production";
|
|
48
48
|
let shardIndex = 0;
|
|
49
49
|
let shardTotal = 1;
|
|
50
|
+
let llmPartsFile = "";
|
|
50
51
|
const excludePaths = ["/_blox_preview"];
|
|
51
52
|
for (const a of argv) {
|
|
52
53
|
if (a === "--crawl") {
|
|
@@ -82,6 +83,8 @@ Environment:
|
|
|
82
83
|
mode = a.slice("--mode=".length);
|
|
83
84
|
} else if (a.startsWith("--exclude=")) {
|
|
84
85
|
excludePaths.push(a.slice("--exclude=".length));
|
|
86
|
+
} else if (a.startsWith("--llm-parts=")) {
|
|
87
|
+
llmPartsFile = a.slice("--llm-parts=".length);
|
|
85
88
|
} else {
|
|
86
89
|
extraPaths.push(a);
|
|
87
90
|
}
|
|
@@ -167,7 +170,20 @@ Environment:
|
|
|
167
170
|
website,
|
|
168
171
|
websiteId,
|
|
169
172
|
redirects,
|
|
170
|
-
collections
|
|
173
|
+
collections,
|
|
174
|
+
// LLM artifacts (llms.txt, llms-full.txt, per-page JSON-LD). On by
|
|
175
|
+
// default; opt out with BLOX_SSG_LLM=0. Skip the *file* artifacts when
|
|
176
|
+
// sharding (>1 shard) because the writing shard only has its own slice of
|
|
177
|
+
// pages — JSON-LD (per-page, in-head) is still emitted on every shard.
|
|
178
|
+
llm: {
|
|
179
|
+
enabled: process.env.BLOX_SSG_LLM !== "0",
|
|
180
|
+
// llms.txt/full need the FULL page list. Unsharded → write directly.
|
|
181
|
+
// Sharded → each shard writes a part file (via --llm-parts) and the
|
|
182
|
+
// coordinator merges them. Per-page JSON-LD is emitted on every shard.
|
|
183
|
+
writeIndex: shardTotal === 1 && !llmPartsFile,
|
|
184
|
+
partsFile: llmPartsFile || void 0,
|
|
185
|
+
fullText: process.env.BLOX_SSG_LLM_FULL !== "0"
|
|
186
|
+
}
|
|
171
187
|
});
|
|
172
188
|
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
173
189
|
console.log(`
|
package/dist/ssg/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import process from "node:process";
|
|
3
|
-
import { p as polyfillBloxSsgGlobals, f as fetchCmsSiteData, a as prerender } from "../prerender-
|
|
3
|
+
import { p as polyfillBloxSsgGlobals, f as fetchCmsSiteData, a as prerender } from "../prerender-DnqZAE4x.js";
|
|
4
4
|
function installFetchTimeout() {
|
|
5
5
|
const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
|
|
6
6
|
const original = globalThis.fetch;
|
|
@@ -46,6 +46,7 @@ async function main() {
|
|
|
46
46
|
let mode = "production";
|
|
47
47
|
let shardIndex = 0;
|
|
48
48
|
let shardTotal = 1;
|
|
49
|
+
let llmPartsFile = "";
|
|
49
50
|
const excludePaths = ["/_blox_preview"];
|
|
50
51
|
for (const a of argv) {
|
|
51
52
|
if (a === "--crawl") {
|
|
@@ -81,6 +82,8 @@ Environment:
|
|
|
81
82
|
mode = a.slice("--mode=".length);
|
|
82
83
|
} else if (a.startsWith("--exclude=")) {
|
|
83
84
|
excludePaths.push(a.slice("--exclude=".length));
|
|
85
|
+
} else if (a.startsWith("--llm-parts=")) {
|
|
86
|
+
llmPartsFile = a.slice("--llm-parts=".length);
|
|
84
87
|
} else {
|
|
85
88
|
extraPaths.push(a);
|
|
86
89
|
}
|
|
@@ -166,7 +169,20 @@ Environment:
|
|
|
166
169
|
website,
|
|
167
170
|
websiteId,
|
|
168
171
|
redirects,
|
|
169
|
-
collections
|
|
172
|
+
collections,
|
|
173
|
+
// LLM artifacts (llms.txt, llms-full.txt, per-page JSON-LD). On by
|
|
174
|
+
// default; opt out with BLOX_SSG_LLM=0. Skip the *file* artifacts when
|
|
175
|
+
// sharding (>1 shard) because the writing shard only has its own slice of
|
|
176
|
+
// pages — JSON-LD (per-page, in-head) is still emitted on every shard.
|
|
177
|
+
llm: {
|
|
178
|
+
enabled: process.env.BLOX_SSG_LLM !== "0",
|
|
179
|
+
// llms.txt/full need the FULL page list. Unsharded → write directly.
|
|
180
|
+
// Sharded → each shard writes a part file (via --llm-parts) and the
|
|
181
|
+
// coordinator merges them. Per-page JSON-LD is emitted on every shard.
|
|
182
|
+
writeIndex: shardTotal === 1 && !llmPartsFile,
|
|
183
|
+
partsFile: llmPartsFile || void 0,
|
|
184
|
+
fullText: process.env.BLOX_SSG_LLM_FULL !== "0"
|
|
185
|
+
}
|
|
170
186
|
});
|
|
171
187
|
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
172
188
|
console.log(`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSSREntry.d.ts","sourceRoot":"","sources":["../../src/ssg/createSSREntry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,SAAS,EAAE,MAAM,KAAK,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAY9D,MAAM,WAAW,yBAAyB;IACzC,oCAAoC;IACpC,aAAa,EAAE,SAAS,CAAA;IACxB;;;;OAIG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9D;;;OAGG;IACH,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACpD,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,oGAAoG;IACpG,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,OAAO,KAAK,EAAE,MAAM,GAAG,CAAC,OAAO,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,CAAA;IAC5E;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;CAC5C;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;IAClE,0EAA0E;IAC1E,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACnD;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"createSSREntry.d.ts","sourceRoot":"","sources":["../../src/ssg/createSSREntry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,SAAS,EAAE,MAAM,KAAK,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAY9D,MAAM,WAAW,yBAAyB;IACzC,oCAAoC;IACpC,aAAa,EAAE,SAAS,CAAA;IACxB;;;;OAIG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9D;;;OAGG;IACH,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACpD,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,oGAAoG;IACpG,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,OAAO,KAAK,EAAE,MAAM,GAAG,CAAC,OAAO,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,CAAA;IAC5E;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;CAC5C;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;IAClE,0EAA0E;IAC1E,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACnD;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,YAAY,CAoLnF"}
|
package/dist/ssg/index.cjs
CHANGED
|
@@ -22,12 +22,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
22
|
mod
|
|
23
23
|
));
|
|
24
24
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
25
|
-
const prerender = require("../prerender-
|
|
25
|
+
const prerender = require("../prerender-jcemLPiq.cjs");
|
|
26
26
|
const ssg_client = require("./client.cjs");
|
|
27
27
|
const pinia = require("pinia");
|
|
28
28
|
const vue = require("vue");
|
|
29
29
|
const routes = require("../routes-Bgy7bXEP.cjs");
|
|
30
30
|
async function renderBloxSsgPage(options) {
|
|
31
|
+
var _a, _b, _c;
|
|
31
32
|
const {
|
|
32
33
|
url,
|
|
33
34
|
resolvedData,
|
|
@@ -40,7 +41,8 @@ async function renderBloxSsgPage(options) {
|
|
|
40
41
|
locale,
|
|
41
42
|
website = null,
|
|
42
43
|
websiteId = "",
|
|
43
|
-
collections
|
|
44
|
+
collections,
|
|
45
|
+
llm
|
|
44
46
|
} = options;
|
|
45
47
|
const g = globalThis;
|
|
46
48
|
const prevState = g[stateWindowKey];
|
|
@@ -59,7 +61,7 @@ async function renderBloxSsgPage(options) {
|
|
|
59
61
|
const seoOverride = seoHead && Object.keys(seoHead).length > 0 ? seoHead : void 0;
|
|
60
62
|
const bloxData = dataRegistry && collectData ? collectData(dataRegistry) : {};
|
|
61
63
|
const dataScript = Object.keys(bloxData).length > 0 ? `<script>window[${JSON.stringify(routes.BLOX_DATA_WINDOW_KEY)}]=${safeJson(bloxData)};${"<"}/script>` : "";
|
|
62
|
-
|
|
64
|
+
let head = prerender.buildPageHead({
|
|
63
65
|
url,
|
|
64
66
|
resolvedData,
|
|
65
67
|
website,
|
|
@@ -67,9 +69,35 @@ async function renderBloxSsgPage(options) {
|
|
|
67
69
|
override: seoOverride,
|
|
68
70
|
stateScript: [stateScript, collectionsScript, websiteIdScript, dataScript].filter(Boolean).join("\n")
|
|
69
71
|
});
|
|
72
|
+
const seoData = resolvedData;
|
|
73
|
+
const primary = prerender.primaryContextEntry(seoData == null ? void 0 : seoData.contexts);
|
|
74
|
+
if ((llm == null ? void 0 : llm.jsonLd) !== false) {
|
|
75
|
+
const jsonLd = prerender.buildJsonLd({
|
|
76
|
+
url,
|
|
77
|
+
page: seoData == null ? void 0 : seoData.page,
|
|
78
|
+
website,
|
|
79
|
+
contextKey: primary == null ? void 0 : primary.key,
|
|
80
|
+
context: primary == null ? void 0 : primary.ctx,
|
|
81
|
+
locale,
|
|
82
|
+
config: llm
|
|
83
|
+
});
|
|
84
|
+
if (jsonLd) head += `
|
|
85
|
+
${jsonLd}`;
|
|
86
|
+
}
|
|
87
|
+
let llmEntry;
|
|
88
|
+
if ((llm == null ? void 0 : llm.enabled) !== false) {
|
|
89
|
+
const title = (seoOverride == null ? void 0 : seoOverride.title) || ((_a = seoData == null ? void 0 : seoData.page) == null ? void 0 : _a.meta_title) || ((_b = seoData == null ? void 0 : seoData.page) == null ? void 0 : _b.title) || "";
|
|
90
|
+
const description = (seoOverride == null ? void 0 : seoOverride.description) || ((_c = seoData == null ? void 0 : seoData.page) == null ? void 0 : _c.meta_description) || void 0;
|
|
91
|
+
llmEntry = {
|
|
92
|
+
url,
|
|
93
|
+
title,
|
|
94
|
+
description,
|
|
95
|
+
text: (llm == null ? void 0 : llm.fullText) !== false ? prerender.extractPageText(html) : void 0
|
|
96
|
+
};
|
|
97
|
+
}
|
|
70
98
|
const lang = locale || (website == null ? void 0 : website.default_locale) || "en";
|
|
71
99
|
const htmlAttrs = `lang="${lang}"`;
|
|
72
|
-
return { html, head, htmlAttrs };
|
|
100
|
+
return { html, head, htmlAttrs, llm: llmEntry };
|
|
73
101
|
} finally {
|
|
74
102
|
if (prevState !== void 0) {
|
|
75
103
|
g[stateWindowKey] = prevState;
|
|
@@ -190,7 +218,8 @@ function createBloxSSREntry(options) {
|
|
|
190
218
|
collectSeo: routes.collectBloxSeo,
|
|
191
219
|
website: ctx.website,
|
|
192
220
|
websiteId: ctx.websiteId,
|
|
193
|
-
collections: ctx.collections
|
|
221
|
+
collections: ctx.collections,
|
|
222
|
+
llm: ctx.llm
|
|
194
223
|
});
|
|
195
224
|
}
|
|
196
225
|
async function prefetchResolve(url) {
|
|
@@ -203,14 +232,19 @@ function createBloxSSREntry(options) {
|
|
|
203
232
|
}
|
|
204
233
|
return { render, prefetchResolve };
|
|
205
234
|
}
|
|
235
|
+
exports.buildJsonLd = prerender.buildJsonLd;
|
|
206
236
|
exports.buildPageHead = prerender.buildPageHead;
|
|
207
237
|
exports.buildSiteHead = prerender.buildSiteHead;
|
|
238
|
+
exports.extractPageText = prerender.extractPageText;
|
|
208
239
|
exports.fetchCmsPrerenderPaths = prerender.fetchCmsPrerenderPaths;
|
|
209
240
|
exports.fetchCmsSiteData = prerender.fetchCmsSiteData;
|
|
241
|
+
exports.generateLlmsFullTxt = prerender.generateLlmsFullTxt;
|
|
242
|
+
exports.generateLlmsTxt = prerender.generateLlmsTxt;
|
|
210
243
|
exports.generateNetlifyRedirects = prerender.generateNetlifyRedirects;
|
|
211
244
|
exports.generateRobotsTxt = prerender.generateRobotsTxt;
|
|
212
245
|
exports.generateSitemapXml = prerender.generateSitemapXml;
|
|
213
246
|
exports.getSiteIconFlags = prerender.getSiteIconFlags;
|
|
247
|
+
exports.mergeLlmParts = prerender.mergeLlmParts;
|
|
214
248
|
exports.polyfillBloxSsgGlobals = prerender.polyfillBloxSsgGlobals;
|
|
215
249
|
exports.prerender = prerender.prerender;
|
|
216
250
|
exports.BLOX_COLLECTIONS_WINDOW_KEY = ssg_client.BLOX_COLLECTIONS_WINDOW_KEY;
|
package/dist/ssg/index.d.ts
CHANGED
|
@@ -22,5 +22,7 @@ export { renderBloxSsgPage } from './render-resolved-page';
|
|
|
22
22
|
export type { BloxSsgRouterLike } from './render-resolved-page';
|
|
23
23
|
export { buildPageHead, buildSiteHead, generateNetlifyRedirects, generateRobotsTxt, generateSitemapXml, getSiteIconFlags } from './seo';
|
|
24
24
|
export type { RedirectEntry, SeoPageData } from './seo';
|
|
25
|
+
export { buildJsonLd, extractPageText, generateLlmsFullTxt, generateLlmsTxt, mergeLlmParts } from './llm-artifacts';
|
|
26
|
+
export type { LlmArtifactsConfig, LlmPageEntry } from './llm-artifacts';
|
|
25
27
|
export { installBloxStateCache } from './state-cache';
|
|
26
28
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/ssg/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ssg/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACvE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AACrG;;;;;;;;;;GAUG;AACH,OAAO,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAA;AAC5J,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,YAAY,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAA;AACvI,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ssg/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACvE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AACrG;;;;;;;;;;GAUG;AACH,OAAO,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAA;AAC5J,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,YAAY,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAA;AACvI,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,mBAAmB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACnH,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/ssg/index.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { b as buildPageHead } from "../prerender-
|
|
2
|
-
import {
|
|
1
|
+
import { b as buildPageHead, c as primaryContextEntry, d as buildJsonLd, e as extractPageText } from "../prerender-DnqZAE4x.js";
|
|
2
|
+
import { g, h, f, i, j, k, l, m, n, o, p, a } from "../prerender-DnqZAE4x.js";
|
|
3
3
|
import { BLOX_STATE_WINDOW_KEY, BLOX_COLLECTIONS_WINDOW_KEY, BLOX_WEBSITE_ID_WINDOW_KEY } from "./client.mjs";
|
|
4
4
|
import { BLOX_DATA_WINDOW_KEY, BLOX_PAGE_SEO_WINDOW_KEY, getCollectionCache, getEmbeddedWebsiteId, installBloxStateCache, installCollectionCache } from "./client.mjs";
|
|
5
5
|
import { createPinia } from "pinia";
|
|
6
6
|
import { createSSRApp, h as h2, Suspense, markRaw } from "vue";
|
|
7
7
|
import { B as BLOX_DATA_WINDOW_KEY2, s as setApiOrigin, a as setActiveLocale, c as collectBloxData, b as collectBloxSeo, p as provideBloxData, d as createBlox, g as generateContentRoutes, i as installLocaleAwareResolve } from "../routes-Dkujcgil.js";
|
|
8
8
|
async function renderBloxSsgPage(options) {
|
|
9
|
+
var _a, _b, _c;
|
|
9
10
|
const {
|
|
10
11
|
url,
|
|
11
12
|
resolvedData,
|
|
@@ -18,7 +19,8 @@ async function renderBloxSsgPage(options) {
|
|
|
18
19
|
locale,
|
|
19
20
|
website = null,
|
|
20
21
|
websiteId = "",
|
|
21
|
-
collections
|
|
22
|
+
collections,
|
|
23
|
+
llm
|
|
22
24
|
} = options;
|
|
23
25
|
const g2 = globalThis;
|
|
24
26
|
const prevState = g2[stateWindowKey];
|
|
@@ -37,7 +39,7 @@ async function renderBloxSsgPage(options) {
|
|
|
37
39
|
const seoOverride = seoHead && Object.keys(seoHead).length > 0 ? seoHead : void 0;
|
|
38
40
|
const bloxData = dataRegistry && collectData ? collectData(dataRegistry) : {};
|
|
39
41
|
const dataScript = Object.keys(bloxData).length > 0 ? `<script>window[${JSON.stringify(BLOX_DATA_WINDOW_KEY2)}]=${safeJson(bloxData)};${"<"}/script>` : "";
|
|
40
|
-
|
|
42
|
+
let head = buildPageHead({
|
|
41
43
|
url,
|
|
42
44
|
resolvedData,
|
|
43
45
|
website,
|
|
@@ -45,9 +47,35 @@ async function renderBloxSsgPage(options) {
|
|
|
45
47
|
override: seoOverride,
|
|
46
48
|
stateScript: [stateScript, collectionsScript, websiteIdScript, dataScript].filter(Boolean).join("\n")
|
|
47
49
|
});
|
|
50
|
+
const seoData = resolvedData;
|
|
51
|
+
const primary = primaryContextEntry(seoData == null ? void 0 : seoData.contexts);
|
|
52
|
+
if ((llm == null ? void 0 : llm.jsonLd) !== false) {
|
|
53
|
+
const jsonLd = buildJsonLd({
|
|
54
|
+
url,
|
|
55
|
+
page: seoData == null ? void 0 : seoData.page,
|
|
56
|
+
website,
|
|
57
|
+
contextKey: primary == null ? void 0 : primary.key,
|
|
58
|
+
context: primary == null ? void 0 : primary.ctx,
|
|
59
|
+
locale,
|
|
60
|
+
config: llm
|
|
61
|
+
});
|
|
62
|
+
if (jsonLd) head += `
|
|
63
|
+
${jsonLd}`;
|
|
64
|
+
}
|
|
65
|
+
let llmEntry;
|
|
66
|
+
if ((llm == null ? void 0 : llm.enabled) !== false) {
|
|
67
|
+
const title = (seoOverride == null ? void 0 : seoOverride.title) || ((_a = seoData == null ? void 0 : seoData.page) == null ? void 0 : _a.meta_title) || ((_b = seoData == null ? void 0 : seoData.page) == null ? void 0 : _b.title) || "";
|
|
68
|
+
const description = (seoOverride == null ? void 0 : seoOverride.description) || ((_c = seoData == null ? void 0 : seoData.page) == null ? void 0 : _c.meta_description) || void 0;
|
|
69
|
+
llmEntry = {
|
|
70
|
+
url,
|
|
71
|
+
title,
|
|
72
|
+
description,
|
|
73
|
+
text: (llm == null ? void 0 : llm.fullText) !== false ? extractPageText(html) : void 0
|
|
74
|
+
};
|
|
75
|
+
}
|
|
48
76
|
const lang = locale || (website == null ? void 0 : website.default_locale) || "en";
|
|
49
77
|
const htmlAttrs = `lang="${lang}"`;
|
|
50
|
-
return { html, head, htmlAttrs };
|
|
78
|
+
return { html, head, htmlAttrs, llm: llmEntry };
|
|
51
79
|
} finally {
|
|
52
80
|
if (prevState !== void 0) {
|
|
53
81
|
g2[stateWindowKey] = prevState;
|
|
@@ -150,8 +178,8 @@ function createBloxSSREntry(options) {
|
|
|
150
178
|
} else {
|
|
151
179
|
try {
|
|
152
180
|
resolvedData = await fetchResolvedPage(slug, pageLocale);
|
|
153
|
-
} catch (
|
|
154
|
-
console.warn(`[prerender] Could not resolve: ${url} — ${
|
|
181
|
+
} catch (e) {
|
|
182
|
+
console.warn(`[prerender] Could not resolve: ${url} — ${e.message}`);
|
|
155
183
|
}
|
|
156
184
|
}
|
|
157
185
|
const { renderToString } = await import("vue/server-renderer");
|
|
@@ -168,7 +196,8 @@ function createBloxSSREntry(options) {
|
|
|
168
196
|
collectSeo: collectBloxSeo,
|
|
169
197
|
website: ctx.website,
|
|
170
198
|
websiteId: ctx.websiteId,
|
|
171
|
-
collections: ctx.collections
|
|
199
|
+
collections: ctx.collections,
|
|
200
|
+
llm: ctx.llm
|
|
172
201
|
});
|
|
173
202
|
}
|
|
174
203
|
async function prefetchResolve(url) {
|
|
@@ -187,19 +216,24 @@ export {
|
|
|
187
216
|
BLOX_PAGE_SEO_WINDOW_KEY,
|
|
188
217
|
BLOX_STATE_WINDOW_KEY,
|
|
189
218
|
BLOX_WEBSITE_ID_WINDOW_KEY,
|
|
219
|
+
buildJsonLd,
|
|
190
220
|
buildPageHead,
|
|
191
|
-
|
|
221
|
+
g as buildSiteHead,
|
|
192
222
|
createBloxSSREntry,
|
|
193
|
-
|
|
223
|
+
extractPageText,
|
|
224
|
+
h as fetchCmsPrerenderPaths,
|
|
194
225
|
f as fetchCmsSiteData,
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
226
|
+
i as generateLlmsFullTxt,
|
|
227
|
+
j as generateLlmsTxt,
|
|
228
|
+
k as generateNetlifyRedirects,
|
|
229
|
+
l as generateRobotsTxt,
|
|
230
|
+
m as generateSitemapXml,
|
|
198
231
|
getCollectionCache,
|
|
199
232
|
getEmbeddedWebsiteId,
|
|
200
|
-
|
|
233
|
+
n as getSiteIconFlags,
|
|
201
234
|
installBloxStateCache,
|
|
202
235
|
installCollectionCache,
|
|
236
|
+
o as mergeLlmParts,
|
|
203
237
|
p as polyfillBloxSsgGlobals,
|
|
204
238
|
a as prerender,
|
|
205
239
|
renderBloxSsgPage
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { PageRead, WebsiteRead } from '../api/types';
|
|
2
|
+
/** Per-project configuration for the LLM artifacts (all optional). */
|
|
3
|
+
export interface LlmArtifactsConfig {
|
|
4
|
+
/** Master switch for ALL llm artifacts (JSON-LD + llms.txt). Default true. */
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Write `llms.txt` / `llms-full.txt`. Default true. MUST be false when
|
|
8
|
+
* sharding (>1 shard), since the writing shard only holds its own page slice
|
|
9
|
+
* and would emit an incomplete index. Per-page JSON-LD is unaffected.
|
|
10
|
+
*/
|
|
11
|
+
writeIndex?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* When set, each (sharded) render writes its collected page extracts to this
|
|
14
|
+
* JSON file instead of the index. A coordinator merges the parts into the
|
|
15
|
+
* final llms.txt/llms-full.txt after all shards finish (see `mergeLlmParts`).
|
|
16
|
+
* The prerender substitutes `{shard}` with the shard index.
|
|
17
|
+
*/
|
|
18
|
+
partsFile?: string;
|
|
19
|
+
/** Also emit `llms-full.txt` (full page-text dump). Default true. */
|
|
20
|
+
fullText?: boolean;
|
|
21
|
+
/** Emit per-page JSON-LD (WebPage/BreadcrumbList/entity). Default true. */
|
|
22
|
+
jsonLd?: boolean;
|
|
23
|
+
/** Custom intro paragraph placed under the H1 in `llms.txt`. */
|
|
24
|
+
intro?: string;
|
|
25
|
+
/** Paths (exact or prefix with trailing `*`) to omit from llms.txt/full. */
|
|
26
|
+
excludePaths?: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Map a primary context key → JSON-LD `@type`, overriding the heuristic.
|
|
29
|
+
* e.g. `{ '$listing': 'Product', '$story': 'Article' }`.
|
|
30
|
+
*/
|
|
31
|
+
typeMap?: Record<string, string>;
|
|
32
|
+
/**
|
|
33
|
+
* Group llms.txt links into sections by path prefix, in order.
|
|
34
|
+
* e.g. `[{ title: 'Blog', prefix: '/blog' }, { title: 'Shop', prefix: '/products' }]`.
|
|
35
|
+
* Unmatched pages fall under a "Pages" section.
|
|
36
|
+
*/
|
|
37
|
+
sections?: Array<{
|
|
38
|
+
title: string;
|
|
39
|
+
prefix: string;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
/** One page's LLM-relevant extract, collected during render. */
|
|
43
|
+
export interface LlmPageEntry {
|
|
44
|
+
url: string;
|
|
45
|
+
title: string;
|
|
46
|
+
description?: string;
|
|
47
|
+
/** Plain-text body (chrome stripped) — only present when fullText enabled. */
|
|
48
|
+
text?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build per-page JSON-LD `<script>` tags.
|
|
52
|
+
*
|
|
53
|
+
* Always emits `WebPage` + `BreadcrumbList`. On data-bound detail pages, also
|
|
54
|
+
* emits a typed entity (`Article`/`Product`/`Event`) derived from the primary
|
|
55
|
+
* context key (overridable via `config.typeMap`).
|
|
56
|
+
*/
|
|
57
|
+
export declare function buildJsonLd(options: {
|
|
58
|
+
url: string;
|
|
59
|
+
page: PageRead | undefined;
|
|
60
|
+
website: WebsiteRead | null;
|
|
61
|
+
contextKey?: string;
|
|
62
|
+
context?: Record<string, unknown>;
|
|
63
|
+
locale?: string;
|
|
64
|
+
config?: LlmArtifactsConfig;
|
|
65
|
+
}): string;
|
|
66
|
+
/**
|
|
67
|
+
* Generate a spec-style `llms.txt`: an H1 site name, a blockquote summary,
|
|
68
|
+
* optional intro, then grouped Markdown links to every indexable page.
|
|
69
|
+
*/
|
|
70
|
+
export declare function generateLlmsTxt(options: {
|
|
71
|
+
website: WebsiteRead | null;
|
|
72
|
+
pages: LlmPageEntry[];
|
|
73
|
+
config?: LlmArtifactsConfig;
|
|
74
|
+
}): string;
|
|
75
|
+
/**
|
|
76
|
+
* Generate `llms-full.txt`: the full readable text of every page, concatenated
|
|
77
|
+
* as Markdown sections. Lets an agent ingest the whole site in a single fetch.
|
|
78
|
+
*/
|
|
79
|
+
export declare function generateLlmsFullTxt(options: {
|
|
80
|
+
website: WebsiteRead | null;
|
|
81
|
+
pages: LlmPageEntry[];
|
|
82
|
+
config?: LlmArtifactsConfig;
|
|
83
|
+
}): string;
|
|
84
|
+
/**
|
|
85
|
+
* Reduce rendered page HTML to readable plain text for `llms-full.txt`.
|
|
86
|
+
*
|
|
87
|
+
* Strips `<script>/<style>/<noscript>`, drops `<nav>/<header>/<footer>` chrome,
|
|
88
|
+
* converts headings/paragraphs/list items/breaks to newlines, removes remaining
|
|
89
|
+
* tags, decodes basic entities, and collapses whitespace. Best-effort and
|
|
90
|
+
* regex-based (no DOM in the SSG worker), which is fine for a text corpus.
|
|
91
|
+
*/
|
|
92
|
+
export declare function extractPageText(html: string): string;
|
|
93
|
+
export declare function isPathExcluded(path: string, patterns: string[] | undefined): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Merge per-shard LLM part files (each a JSON array of `LlmPageEntry`) into the
|
|
96
|
+
* final `llms.txt` / `llms-full.txt`. Run by the sharded coordinator after all
|
|
97
|
+
* shards finish. De-dupes by URL (last write wins) and sorts.
|
|
98
|
+
*/
|
|
99
|
+
export declare function mergeLlmParts(options: {
|
|
100
|
+
partFiles: string[];
|
|
101
|
+
outDir: string;
|
|
102
|
+
website: WebsiteRead | null;
|
|
103
|
+
config?: LlmArtifactsConfig;
|
|
104
|
+
}): Promise<{
|
|
105
|
+
pages: number;
|
|
106
|
+
}>;
|
|
107
|
+
//# sourceMappingURL=llm-artifacts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-artifacts.d.ts","sourceRoot":"","sources":["../../src/ssg/llm-artifacts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAMzD,sEAAsE;AACtE,MAAM,WAAW,kBAAkB;IAClC,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACnD;AAED,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAA;CACb;AA0CD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;IAC1B,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAC3B,GAAG,MAAM,CAiET;AAMD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACxC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAC3B,GAAG,MAAM,CAwCT;AAMD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAC5C,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAC3B,GAAG,MAAM,CAmBT;AAMD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqBpD;AAMD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,OAAO,CAMpF;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAC5C,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAC3B,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA0B7B"}
|
package/dist/ssg/prerender.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { WebsiteRead } from '../api/types';
|
|
2
2
|
import { RedirectEntry } from './seo';
|
|
3
|
+
import { LlmArtifactsConfig, LlmPageEntry } from './llm-artifacts';
|
|
3
4
|
type ExcludeRule = string | RegExp | ((path: string) => boolean);
|
|
4
5
|
export interface PrerenderOptions {
|
|
5
6
|
root?: string;
|
|
@@ -29,6 +30,8 @@ export interface PrerenderOptions {
|
|
|
29
30
|
redirects?: RedirectEntry[];
|
|
30
31
|
/** Pre-fetched datastore collections keyed by "store/collection". */
|
|
31
32
|
collections?: Record<string, unknown[]>;
|
|
33
|
+
/** LLM artifacts config (llms.txt, llms-full.txt, per-page JSON-LD). */
|
|
34
|
+
llm?: LlmArtifactsConfig;
|
|
32
35
|
}
|
|
33
36
|
export interface RenderContext {
|
|
34
37
|
manifest: Record<string, string[]> | null;
|
|
@@ -46,6 +49,8 @@ export interface RenderContext {
|
|
|
46
49
|
* that 404'd (non-CMS route) — cached as a negative to avoid refetching.
|
|
47
50
|
*/
|
|
48
51
|
resolveCache?: Map<string, unknown>;
|
|
52
|
+
/** LLM artifacts config, threaded to the SSR entry for JSON-LD + text. */
|
|
53
|
+
llm?: LlmArtifactsConfig;
|
|
49
54
|
}
|
|
50
55
|
export interface RenderResult {
|
|
51
56
|
html: string;
|
|
@@ -54,6 +59,8 @@ export interface RenderResult {
|
|
|
54
59
|
state?: unknown;
|
|
55
60
|
/** Optional ISO last-modified for this page → sitemap <lastmod>. */
|
|
56
61
|
lastmod?: string;
|
|
62
|
+
/** Per-page LLM extract (title/description/text) for llms.txt artifacts. */
|
|
63
|
+
llm?: LlmPageEntry;
|
|
57
64
|
}
|
|
58
65
|
export interface PrerenderResult {
|
|
59
66
|
rendered: string[];
|
|
@@ -87,6 +94,6 @@ export declare function prerender({ root, clientOutDir, serverEntry, paths, craw
|
|
|
87
94
|
* sharded runner divides a global budget by the shard count. 0 disables
|
|
88
95
|
* prefetch (render resolves inline). Default 8.
|
|
89
96
|
*/
|
|
90
|
-
resolvePrefetchConcurrency, mode, website, websiteId, redirects, collections, }?: PrerenderOptions): Promise<PrerenderResult>;
|
|
97
|
+
resolvePrefetchConcurrency, mode, website, websiteId, redirects, collections, llm, }?: PrerenderOptions): Promise<PrerenderResult>;
|
|
91
98
|
export {};
|
|
92
99
|
//# sourceMappingURL=prerender.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prerender.d.ts","sourceRoot":"","sources":["../../src/ssg/prerender.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"prerender.d.ts","sourceRoot":"","sources":["../../src/ssg/prerender.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { WebsiteRead } from '../api/types';
|
|
2
2
|
import { BloxDataRegistry, BloxSeoHead } from '../data/useData';
|
|
3
|
+
import { LlmArtifactsConfig, LlmPageEntry } from './llm-artifacts';
|
|
3
4
|
export interface BloxSsgRouterLike {
|
|
4
5
|
push: (url: string) => Promise<void>;
|
|
5
6
|
isReady: () => Promise<void>;
|
|
@@ -44,9 +45,12 @@ export declare function renderBloxSsgPage<TApp>(options: {
|
|
|
44
45
|
websiteId?: string;
|
|
45
46
|
/** Pre-fetched datastore collections — embedded for zero-fetch hydration. */
|
|
46
47
|
collections?: Record<string, unknown[]>;
|
|
48
|
+
/** LLM artifacts config — gates JSON-LD injection + llms.txt text capture. */
|
|
49
|
+
llm?: LlmArtifactsConfig;
|
|
47
50
|
}): Promise<{
|
|
48
51
|
html: string;
|
|
49
52
|
head?: string;
|
|
50
53
|
htmlAttrs?: string;
|
|
54
|
+
llm?: LlmPageEntry;
|
|
51
55
|
}>;
|
|
52
56
|
//# sourceMappingURL=render-resolved-page.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-resolved-page.d.ts","sourceRoot":"","sources":["../../src/ssg/render-resolved-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"render-resolved-page.d.ts","sourceRoot":"","sources":["../../src/ssg/render-resolved-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAIpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAGvE,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE;IACtD,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,OAAO,GAAG,IAAI,CAAA;IAC5B,cAAc,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC9C,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK;QAAE,GAAG,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,iBAAiB,CAAC;QAAC,YAAY,CAAC,EAAE,gBAAgB,CAAA;KAAE,CAAA;IAC3G,8EAA8E;IAC9E,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrE,sEAAsE;IACtE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,WAAW,CAAA;IACxD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+EAA+E;IAC/E,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IAC5B,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;IACvC,8EAA8E;IAC9E,GAAG,CAAC,EAAE,kBAAkB,CAAA;CACxB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,YAAY,CAAA;CAAE,CAAC,CA+GnF"}
|
package/dist/ssg/seo.d.ts
CHANGED
|
@@ -91,4 +91,28 @@ export declare function getSiteIconFlags(website: WebsiteRead | null): {
|
|
|
91
91
|
hasFavicon: boolean;
|
|
92
92
|
hasWebclip: boolean;
|
|
93
93
|
};
|
|
94
|
+
interface ContextSeoFields {
|
|
95
|
+
title: string | null;
|
|
96
|
+
description: string | null;
|
|
97
|
+
image: string | null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Extract SEO-relevant fields from the primary data-binding context.
|
|
101
|
+
*
|
|
102
|
+
* For template pages like `/blog/:slug`, the resolved page data contains
|
|
103
|
+
* `contexts: { $post: { title, excerpt, cover_image_url, … } }`.
|
|
104
|
+
* We look for common field names and return them as fallback SEO values.
|
|
105
|
+
*/
|
|
106
|
+
export declare function extractPrimaryContext(contexts: Record<string, Record<string, unknown> | null> | undefined): ContextSeoFields;
|
|
107
|
+
/**
|
|
108
|
+
* Return the primary (first non-null) data-binding context along with its key.
|
|
109
|
+
* The key (e.g. `$post`, `$product`, `$event`) drives the JSON-LD `@type`
|
|
110
|
+
* heuristic; the object supplies the entity fields. Returns `null` when the
|
|
111
|
+
* page has no bound context (a regular CMS page).
|
|
112
|
+
*/
|
|
113
|
+
export declare function primaryContextEntry(contexts: Record<string, Record<string, unknown> | null> | undefined): {
|
|
114
|
+
key: string;
|
|
115
|
+
ctx: Record<string, unknown>;
|
|
116
|
+
} | null;
|
|
117
|
+
export {};
|
|
94
118
|
//# sourceMappingURL=seo.d.ts.map
|
package/dist/ssg/seo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../../src/ssg/seo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAMzE,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,QAAQ,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;CACzD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAWlG;AAED,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;CACnB;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE;IACtC,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,WAAW,GAAG,IAAI,CAAA;IAChC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAA;IACxG;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG,MAAM,CAgHT;AAMD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAwCjE;AAMD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC3C,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC,GAAG,MAAM,CAqBT;AAMD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IAC1C,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB,GAAG,MAAM,CAmBT;AAMD,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,MAAM,CAK3E;AAMD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1D,MAAM,CA8BR;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG;IAC9D,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;CACnB,CAMA"}
|
|
1
|
+
{"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../../src/ssg/seo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAMzE,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,QAAQ,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;CACzD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAWlG;AAED,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;CACnB;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE;IACtC,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,WAAW,GAAG,IAAI,CAAA;IAChC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAA;IACxG;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG,MAAM,CAgHT;AAMD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAwCjE;AAMD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC3C,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC,GAAG,MAAM,CAqBT;AAMD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IAC1C,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB,GAAG,MAAM,CAmBT;AAMD,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,MAAM,CAK3E;AAMD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1D,MAAM,CA8BR;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG;IAC9D,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;CACnB,CAMA;AAMD,UAAU,gBAAgB;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,SAAS,GAClE,gBAAgB,CAmBlB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,SAAS,GAClE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,IAAI,CAMtD"}
|
package/package.json
CHANGED