@bagelink/blox 1.15.271 → 1.15.275

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.
@@ -1 +1 @@
1
- {"version":3,"file":"CmsPageView.vue.d.ts","sourceRoot":"","sources":["../src/CmsPageView.vue"],"names":[],"mappings":";AAodA,wBAMG"}
1
+ {"version":3,"file":"CmsPageView.vue.d.ts","sourceRoot":"","sources":["../src/CmsPageView.vue"],"names":[],"mappings":";AAgxBA,wBAMG"}
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const PreviewApp_vue_vue_type_style_index_0_lang = require("./PreviewApp.vue_vue_type_style_index_0_lang-CnKU05t1.cjs");
3
+ const PreviewApp_vue_vue_type_style_index_0_lang = require("./PreviewApp.vue_vue_type_style_index_0_lang-CpZt3b1X.cjs");
4
4
  exports.default = PreviewApp_vue_vue_type_style_index_0_lang._sfc_main;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "./PreviewApp.vue_vue_type_style_index_0_lang-DuHZmbcn.js";
1
+ import { _ as _sfc_main } from "./PreviewApp.vue_vue_type_style_index_0_lang-DIKjhzD_.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  const vue = require("vue");
3
- const routes = require("./routes-CfwE_uYV.cjs");
3
+ const routes = require("./routes-B4RYeiGa.cjs");
4
4
  function sendToEditor(msg) {
5
5
  window.parent.postMessage(cloneForPostMessage(msg), "*");
6
6
  }
@@ -1,5 +1,5 @@
1
1
  import { defineComponent, inject, ref, h, provide, onMounted, onUnmounted, openBlock, createElementBlock, createVNode, unref, nextTick } from "vue";
2
- import { e as BLOX_REGISTRY_KEY, u as useLocale } from "./routes-D5aVOcFs.js";
2
+ import { e as BLOX_REGISTRY_KEY, u as useLocale } from "./routes-DE0OIzJr.js";
3
3
  function sendToEditor(msg) {
4
4
  window.parent.postMessage(cloneForPostMessage(msg), "*");
5
5
  }
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const routes = require("./routes-CfwE_uYV.cjs");
4
- const PreviewApp_vue_vue_type_style_index_0_lang = require("./PreviewApp.vue_vue_type_style_index_0_lang-CnKU05t1.cjs");
3
+ const routes = require("./routes-B4RYeiGa.cjs");
4
+ const PreviewApp_vue_vue_type_style_index_0_lang = require("./PreviewApp.vue_vue_type_style_index_0_lang-CpZt3b1X.cjs");
5
5
  const vue = require("vue");
6
6
  const vueRouter = require("vue-router");
7
7
  const pinia = require("pinia");
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { f as BLOX_LOCALE_STRATEGY_KEY, u as useLocale, n as normalizeLink, h as useSeo, j as getRegistryData, k as getItemBySlug, l as getItemById, m as getContentRoute, p as provideBloxData, d as createBlox, g as generateContentRoutes, o as installContentFallback, i as installLocaleAwareResolve, a as setActiveLocale, q as installSmartLinks, r as consumePendingLocaleSwitch } from "./routes-D5aVOcFs.js";
2
- import { _, t, v, w, B, x, y, z, A, C, P, D, E, c, b, F, G, H, I, J, K, L, M, N, O, Q, R, S, s, T, U, V, W } from "./routes-D5aVOcFs.js";
3
- import { _ as _2, P as P2, s as s2, a } from "./PreviewApp.vue_vue_type_style_index_0_lang-DuHZmbcn.js";
1
+ import { f as BLOX_LOCALE_STRATEGY_KEY, u as useLocale, n as normalizeLink, h as useSeo, j as getRegistryData, k as getItemBySlug, l as getItemById, m as getContentRoute, p as provideBloxData, d as createBlox, g as generateContentRoutes, o as installContentFallback, i as installLocaleAwareResolve, a as setActiveLocale, q as installSmartLinks, r as consumePendingLocaleSwitch } from "./routes-DE0OIzJr.js";
2
+ import { _, t, v, w, B, x, y, z, A, C, P, D, E, c, b, F, G, H, I, J, K, L, M, N, O, Q, R, S, s, T, U, V, W } from "./routes-DE0OIzJr.js";
3
+ import { _ as _2, P as P2, s as s2, a } from "./PreviewApp.vue_vue_type_style_index_0_lang-DIKjhzD_.js";
4
4
  import { defineComponent, resolveComponent, openBlock, createBlock, withCtx, Transition, resolveDynamicComponent, inject, ref, watch, onMounted, onUnmounted, computed, onServerPrefetch, toValue, createApp, h, Suspense, markRaw } from "vue";
5
5
  import { useRouter, useRoute } from "vue-router";
6
6
  import { createPinia } from "pinia";
@@ -111,6 +111,12 @@ function extractCollectionRefs(pages) {
111
111
  }
112
112
  return refs;
113
113
  }
114
+ const cmsRoutes = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
115
+ __proto__: null,
116
+ expandLocalePaths,
117
+ fetchCmsPrerenderPaths,
118
+ fetchCmsSiteData
119
+ }, Symbol.toStringTag, { value: "Module" }));
114
120
  async function polyfillBloxSsgGlobals(options) {
115
121
  const { env } = await import("node:process");
116
122
  const pageUrl = (options == null ? void 0 : options.pageUrl) ?? env.BAGELINK_API_URL ?? "https://example.com/";
@@ -176,7 +182,7 @@ function buildPageHead(options) {
176
182
  const page = resolvedData == null ? void 0 : resolvedData.page;
177
183
  const ctx = extractPrimaryContext(resolvedData == null ? void 0 : resolvedData.contexts);
178
184
  const siteName = seo.site_name || void 0;
179
- const title = (override == null ? void 0 : override.title) || (page == null ? void 0 : page.meta_title) || ctx.title || ((page == null ? void 0 : page.title) && siteName ? `${page.title} · ${siteName}` : null) || (page == null ? void 0 : page.title) || seo.default_meta_title;
185
+ const title = (override == null ? void 0 : override.title) || ctx.title || (page == null ? void 0 : page.meta_title) || ((page == null ? void 0 : page.title) && siteName ? `${page.title} · ${siteName}` : null) || (page == null ? void 0 : page.title) || seo.default_meta_title;
180
186
  if (title) {
181
187
  const bare = (override == null ? void 0 : override.title) || ctx.title;
182
188
  const fullTitle = bare && siteName && !bare.includes(siteName) ? `${esc(bare)} · ${esc(siteName)}` : esc(title);
@@ -193,7 +199,7 @@ function buildPageHead(options) {
193
199
  } else if (canonicalBase) {
194
200
  parts.push(`<link rel="canonical" href="${esc(canonicalBase + url)}">`);
195
201
  }
196
- const ogTitle = (override == null ? void 0 : override.title) || (page == null ? void 0 : page.meta_title) || ctx.title || (page == null ? void 0 : page.title) || siteName || seo.default_meta_title;
202
+ const ogTitle = (override == null ? void 0 : override.title) || ctx.title || (page == null ? void 0 : page.meta_title) || (page == null ? void 0 : page.title) || siteName || seo.default_meta_title;
197
203
  const ogDesc = (override == null ? void 0 : override.description) || (page == null ? void 0 : page.meta_description) || ctx.description || seo.default_meta_description;
198
204
  const ogImage = absUrl((override == null ? void 0 : override.image) || (page == null ? void 0 : page.og_image) || ctx.image || seo.default_og_image);
199
205
  const isDetailPage = !!((resolvedData == null ? void 0 : resolvedData.contexts) && Object.values(resolvedData.contexts).some((c) => c != null));
@@ -334,7 +340,7 @@ function extractPrimaryContext(contexts) {
334
340
  return typeof v === "string" && v.trim() ? v.trim() : null;
335
341
  };
336
342
  return {
337
- title: str2("meta_title") || str2("title"),
343
+ title: str2("meta_title") || str2("metaTitle") || str2("title") || str2("name") || str2("productName") || str2("displayName"),
338
344
  description: str2("meta_description") || str2("excerpt") || str2("description") || str2("blurb") || str2("summary"),
339
345
  image: str2("og_image") || str2("cover_image_url") || str2("image_url") || str2("image")
340
346
  };
@@ -547,6 +553,15 @@ async function mergeLlmParts(options) {
547
553
  }
548
554
  return { pages: pages.length };
549
555
  }
556
+ const llmArtifacts = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
557
+ __proto__: null,
558
+ buildJsonLd,
559
+ extractPageText,
560
+ generateLlmsFullTxt,
561
+ generateLlmsTxt,
562
+ isPathExcluded,
563
+ mergeLlmParts
564
+ }, Symbol.toStringTag, { value: "Module" }));
550
565
  async function prerender({
551
566
  root = process.cwd(),
552
567
  clientOutDir = "dist/client",
@@ -887,5 +902,7 @@ export {
887
902
  generateSitemapXml as m,
888
903
  getSiteIconFlags as n,
889
904
  mergeLlmParts as o,
890
- polyfillBloxSsgGlobals as p
905
+ polyfillBloxSsgGlobals as p,
906
+ cmsRoutes as q,
907
+ llmArtifacts as r
891
908
  };
@@ -134,6 +134,12 @@ function extractCollectionRefs(pages) {
134
134
  }
135
135
  return refs;
136
136
  }
137
+ const cmsRoutes = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
138
+ __proto__: null,
139
+ expandLocalePaths,
140
+ fetchCmsPrerenderPaths,
141
+ fetchCmsSiteData
142
+ }, Symbol.toStringTag, { value: "Module" }));
137
143
  async function polyfillBloxSsgGlobals(options) {
138
144
  const { env } = await import("node:process");
139
145
  const pageUrl = (options == null ? void 0 : options.pageUrl) ?? env.BAGELINK_API_URL ?? "https://example.com/";
@@ -199,7 +205,7 @@ function buildPageHead(options) {
199
205
  const page = resolvedData == null ? void 0 : resolvedData.page;
200
206
  const ctx = extractPrimaryContext(resolvedData == null ? void 0 : resolvedData.contexts);
201
207
  const siteName = seo.site_name || void 0;
202
- const title = (override == null ? void 0 : override.title) || (page == null ? void 0 : page.meta_title) || ctx.title || ((page == null ? void 0 : page.title) && siteName ? `${page.title} · ${siteName}` : null) || (page == null ? void 0 : page.title) || seo.default_meta_title;
208
+ const title = (override == null ? void 0 : override.title) || ctx.title || (page == null ? void 0 : page.meta_title) || ((page == null ? void 0 : page.title) && siteName ? `${page.title} · ${siteName}` : null) || (page == null ? void 0 : page.title) || seo.default_meta_title;
203
209
  if (title) {
204
210
  const bare = (override == null ? void 0 : override.title) || ctx.title;
205
211
  const fullTitle = bare && siteName && !bare.includes(siteName) ? `${esc(bare)} · ${esc(siteName)}` : esc(title);
@@ -216,7 +222,7 @@ function buildPageHead(options) {
216
222
  } else if (canonicalBase) {
217
223
  parts.push(`<link rel="canonical" href="${esc(canonicalBase + url)}">`);
218
224
  }
219
- const ogTitle = (override == null ? void 0 : override.title) || (page == null ? void 0 : page.meta_title) || ctx.title || (page == null ? void 0 : page.title) || siteName || seo.default_meta_title;
225
+ const ogTitle = (override == null ? void 0 : override.title) || ctx.title || (page == null ? void 0 : page.meta_title) || (page == null ? void 0 : page.title) || siteName || seo.default_meta_title;
220
226
  const ogDesc = (override == null ? void 0 : override.description) || (page == null ? void 0 : page.meta_description) || ctx.description || seo.default_meta_description;
221
227
  const ogImage = absUrl((override == null ? void 0 : override.image) || (page == null ? void 0 : page.og_image) || ctx.image || seo.default_og_image);
222
228
  const isDetailPage = !!((resolvedData == null ? void 0 : resolvedData.contexts) && Object.values(resolvedData.contexts).some((c) => c != null));
@@ -357,7 +363,7 @@ function extractPrimaryContext(contexts) {
357
363
  return typeof v === "string" && v.trim() ? v.trim() : null;
358
364
  };
359
365
  return {
360
- title: str2("meta_title") || str2("title"),
366
+ title: str2("meta_title") || str2("metaTitle") || str2("title") || str2("name") || str2("productName") || str2("displayName"),
361
367
  description: str2("meta_description") || str2("excerpt") || str2("description") || str2("blurb") || str2("summary"),
362
368
  image: str2("og_image") || str2("cover_image_url") || str2("image_url") || str2("image")
363
369
  };
@@ -570,6 +576,15 @@ async function mergeLlmParts(options) {
570
576
  }
571
577
  return { pages: pages.length };
572
578
  }
579
+ const llmArtifacts = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
580
+ __proto__: null,
581
+ buildJsonLd,
582
+ extractPageText,
583
+ generateLlmsFullTxt,
584
+ generateLlmsTxt,
585
+ isPathExcluded,
586
+ mergeLlmParts
587
+ }, Symbol.toStringTag, { value: "Module" }));
573
588
  async function prerender({
574
589
  root = process.cwd(),
575
590
  clientOutDir = "dist/client",
@@ -897,6 +912,7 @@ function discoverInternalLinks(html) {
897
912
  exports.buildJsonLd = buildJsonLd;
898
913
  exports.buildPageHead = buildPageHead;
899
914
  exports.buildSiteHead = buildSiteHead;
915
+ exports.cmsRoutes = cmsRoutes;
900
916
  exports.extractPageText = extractPageText;
901
917
  exports.fetchCmsPrerenderPaths = fetchCmsPrerenderPaths;
902
918
  exports.fetchCmsSiteData = fetchCmsSiteData;
@@ -906,6 +922,7 @@ exports.generateNetlifyRedirects = generateNetlifyRedirects;
906
922
  exports.generateRobotsTxt = generateRobotsTxt;
907
923
  exports.generateSitemapXml = generateSitemapXml;
908
924
  exports.getSiteIconFlags = getSiteIconFlags;
925
+ exports.llmArtifacts = llmArtifacts;
909
926
  exports.mergeLlmParts = mergeLlmParts;
910
927
  exports.polyfillBloxSsgGlobals = polyfillBloxSsgGlobals;
911
928
  exports.prerender = prerender;
@@ -278,17 +278,26 @@ const PageRenderer = vue.defineComponent({
278
278
  });
279
279
  const _hoisted_1$1 = {
280
280
  key: 0,
281
- class: "blox-loading flex column h-100vh justify-content-center"
281
+ class: "blox-loading"
282
282
  };
283
- const _hoisted_2$1 = {
283
+ const _hoisted_2$1 = { class: "w1100px px-1 py-1" };
284
+ const _hoisted_3$1 = { class: "flex space-between pb-1" };
285
+ const _hoisted_4$1 = { class: "flex gap-1" };
286
+ const _hoisted_5 = { class: "grid grid-wrap-2 gap-2 py-2" };
287
+ const _hoisted_6 = { class: "py-1" };
288
+ const _hoisted_7 = { class: "grid grid-wrap-4 gap-col-1 py-2" };
289
+ const _hoisted_8 = { class: "grid grid-wrap-2 grid-span-3 m_grid-span-4 gap-2" };
290
+ const _hoisted_9 = { class: "grid grid-wrap-4 gap-2 py-2" };
291
+ const _hoisted_10 = { class: "grid-span-3" };
292
+ const _hoisted_11 = {
284
293
  key: 1,
285
294
  class: "blox-not-found"
286
295
  };
287
- const _hoisted_3$1 = {
296
+ const _hoisted_12 = {
288
297
  key: 2,
289
298
  class: "blox-error color-red"
290
299
  };
291
- const _hoisted_4$1 = {
300
+ const _hoisted_13 = {
292
301
  key: 0,
293
302
  class: "blox-nav-progress"
294
303
  };
@@ -326,14 +335,30 @@ const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
326
335
  contexts.value = entry.contexts ?? {};
327
336
  currentPageId.value = ((_c = entry.page) == null ? void 0 : _c.id) ?? null;
328
337
  setAlternates(navigableAlternates(entry.alternates, path));
338
+ updateDocumentTitle(entry);
329
339
  return true;
330
340
  }
341
+ function contextTitle(contexts2) {
342
+ if (!contexts2) return null;
343
+ const preferredKeys = ["$page", "$post", "$item", "$article", "$product", "$author"];
344
+ const orderedContexts = [
345
+ ...preferredKeys.map((key) => contexts2[key]),
346
+ ...Object.entries(contexts2).filter(([key]) => !preferredKeys.includes(key)).map(([, context]) => context)
347
+ ];
348
+ const titleFields = ["meta_title", "metaTitle", "title", "name", "productName", "displayName"];
349
+ for (const context of orderedContexts) {
350
+ if (!context) continue;
351
+ for (const field of titleFields) {
352
+ const value = context[field];
353
+ if (typeof value === "string" && value.trim()) return value.trim();
354
+ }
355
+ }
356
+ return null;
357
+ }
331
358
  function updateDocumentTitle(resolved) {
359
+ var _a, _b;
332
360
  if (typeof document === "undefined") return;
333
- const { page } = resolved;
334
- const ctx = resolved.contexts ? Object.values(resolved.contexts).find((c) => c != null) : null;
335
- const ctxTitle = ctx && typeof ctx.title === "string" ? ctx.title : null;
336
- const title = page.meta_title || ctxTitle || page.title;
361
+ const title = contextTitle(resolved.contexts) || ((_a = resolved.page) == null ? void 0 : _a.meta_title) || ((_b = resolved.page) == null ? void 0 : _b.title);
337
362
  if (title) document.title = title;
338
363
  }
339
364
  const initialSlug = (() => {
@@ -393,8 +418,107 @@ const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
393
418
  const _component_RouterLink = vue.resolveComponent("RouterLink");
394
419
  return vue.openBlock(), vue.createElementBlock("div", null, [
395
420
  initialLoading.value && blocks.value.length === 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [
396
- vue.createVNode(vue.unref(vue$1.Loading))
397
- ])) : notFound.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$1, [
421
+ vue.createElementVNode("div", _hoisted_2$1, [
422
+ vue.createElementVNode("div", _hoisted_3$1, [
423
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
424
+ width: "180px",
425
+ height: "42px"
426
+ }),
427
+ vue.createElementVNode("div", _hoisted_4$1, [
428
+ (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, vue.renderList(5, (item) => {
429
+ return vue.createVNode(vue.unref(vue$1.Skeleton), {
430
+ key: item,
431
+ width: "90px",
432
+ height: "20px"
433
+ });
434
+ }), 64))
435
+ ])
436
+ ]),
437
+ vue.createElementVNode("div", _hoisted_5, [
438
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
439
+ width: "100%",
440
+ height: "260px"
441
+ }),
442
+ vue.createElementVNode("div", _hoisted_6, [
443
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
444
+ width: "120px",
445
+ height: "16px",
446
+ class: "mb-1"
447
+ }),
448
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
449
+ width: "92%",
450
+ height: "34px"
451
+ }),
452
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
453
+ width: "72%",
454
+ height: "34px",
455
+ class: "mb-1"
456
+ }),
457
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
458
+ width: "190px",
459
+ height: "16px"
460
+ })
461
+ ])
462
+ ]),
463
+ vue.createElementVNode("div", _hoisted_7, [
464
+ vue.createElementVNode("div", null, [
465
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
466
+ width: "150px",
467
+ height: "28px",
468
+ class: "mb-1"
469
+ }),
470
+ (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, vue.renderList(3, (tab) => {
471
+ return vue.createVNode(vue.unref(vue$1.Skeleton), {
472
+ key: tab,
473
+ width: "90px",
474
+ height: "20px",
475
+ class: "mb-1"
476
+ });
477
+ }), 64))
478
+ ]),
479
+ vue.createElementVNode("div", _hoisted_8, [
480
+ (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, vue.renderList(2, (card) => {
481
+ return vue.createElementVNode("div", { key: card }, [
482
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
483
+ width: "100%",
484
+ height: "210px"
485
+ }),
486
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
487
+ width: "88%",
488
+ height: "24px",
489
+ class: "mt-05"
490
+ }),
491
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
492
+ width: "52%",
493
+ height: "15px"
494
+ })
495
+ ]);
496
+ }), 64))
497
+ ])
498
+ ]),
499
+ vue.createElementVNode("div", _hoisted_9, [
500
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
501
+ width: "100%",
502
+ height: "320px"
503
+ }),
504
+ vue.createElementVNode("div", _hoisted_10, [
505
+ vue.createVNode(vue.unref(vue$1.Skeleton), {
506
+ width: "220px",
507
+ height: "30px",
508
+ class: "mb-1"
509
+ }),
510
+ (vue.openBlock(), vue.createElementBlock(vue.Fragment, null, vue.renderList(5, (row) => {
511
+ return vue.createVNode(vue.unref(vue$1.Skeleton), {
512
+ key: row,
513
+ width: "100%",
514
+ height: "58px",
515
+ class: "mb-05"
516
+ });
517
+ }), 64))
518
+ ])
519
+ ])
520
+ ])
521
+ ])) : notFound.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_11, [
398
522
  _cache[0] || (_cache[0] = vue.createElementVNode("h2", null, "404", -1)),
399
523
  vue.createElementVNode("p", null, vue.toDisplayString(vue.unref(locale2) === "he" ? "הדף לא נמצא" : "Page not found"), 1),
400
524
  vue.createVNode(_component_RouterLink, { to: "/" }, {
@@ -403,8 +527,8 @@ const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
403
527
  ]),
404
528
  _: 1
405
529
  })
406
- ])) : error.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$1, vue.toDisplayString(error.value), 1)) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 3 }, [
407
- navigating.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4$1)) : vue.createCommentVNode("", true),
530
+ ])) : error.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_12, vue.toDisplayString(error.value), 1)) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 3 }, [
531
+ navigating.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_13)) : vue.createCommentVNode("", true),
408
532
  vue.createVNode(vue.unref(PageRenderer), { blocks: blocks.value }, null, 8, ["blocks"])
409
533
  ], 64)),
410
534
  vue.unref(adminConfig) ? (vue.openBlock(), vue.createBlock(_sfc_main$3, {
@@ -834,7 +958,7 @@ class BloxInstance {
834
958
  }
835
959
  router.addRoute({
836
960
  path: "/_blox_preview",
837
- component: () => Promise.resolve().then(() => require("./PreviewApp-9HSW0bCC.cjs")),
961
+ component: () => Promise.resolve().then(() => require("./PreviewApp-1tOhVrq-.cjs")),
838
962
  beforeEnter: () => window.parent !== window ? true : "/"
839
963
  });
840
964
  router.addRoute({ path: "/:pathMatch(.*)*", component: _sfc_main$2 });
@@ -1,10 +1,10 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { inject, computed, ref, defineComponent, onMounted, unref, openBlock, createBlock, Teleport, createElementBlock, createElementVNode, createCommentVNode, h, provide, watch, resolveComponent, createVNode, toDisplayString, withCtx, createTextVNode, Fragment, getCurrentInstance, shallowRef, onServerPrefetch, toValue, markRaw, resolveDynamicComponent } from "vue";
4
+ import { inject, computed, ref, defineComponent, onMounted, unref, openBlock, createBlock, Teleport, createElementBlock, createElementVNode, createCommentVNode, h, provide, watch, resolveComponent, createVNode, Fragment, renderList, toDisplayString, withCtx, createTextVNode, getCurrentInstance, shallowRef, onServerPrefetch, toValue, markRaw, resolveDynamicComponent } from "vue";
5
5
  import { useRoute, useRouter } from "vue-router";
6
6
  import { BLOX_WEBSITE_ID_WINDOW_KEY, BLOX_STATE_WINDOW_KEY } from "./ssg/client.mjs";
7
- import { getI18n, Loading } from "@bagelink/vue";
7
+ import { getI18n, Skeleton } from "@bagelink/vue";
8
8
  let BASE = "/api";
9
9
  let _websiteName = "";
10
10
  let _store = "";
@@ -277,17 +277,26 @@ const PageRenderer = defineComponent({
277
277
  });
278
278
  const _hoisted_1$1 = {
279
279
  key: 0,
280
- class: "blox-loading flex column h-100vh justify-content-center"
280
+ class: "blox-loading"
281
281
  };
282
- const _hoisted_2$1 = {
282
+ const _hoisted_2$1 = { class: "w1100px px-1 py-1" };
283
+ const _hoisted_3$1 = { class: "flex space-between pb-1" };
284
+ const _hoisted_4$1 = { class: "flex gap-1" };
285
+ const _hoisted_5 = { class: "grid grid-wrap-2 gap-2 py-2" };
286
+ const _hoisted_6 = { class: "py-1" };
287
+ const _hoisted_7 = { class: "grid grid-wrap-4 gap-col-1 py-2" };
288
+ const _hoisted_8 = { class: "grid grid-wrap-2 grid-span-3 m_grid-span-4 gap-2" };
289
+ const _hoisted_9 = { class: "grid grid-wrap-4 gap-2 py-2" };
290
+ const _hoisted_10 = { class: "grid-span-3" };
291
+ const _hoisted_11 = {
283
292
  key: 1,
284
293
  class: "blox-not-found"
285
294
  };
286
- const _hoisted_3$1 = {
295
+ const _hoisted_12 = {
287
296
  key: 2,
288
297
  class: "blox-error color-red"
289
298
  };
290
- const _hoisted_4$1 = {
299
+ const _hoisted_13 = {
291
300
  key: 0,
292
301
  class: "blox-nav-progress"
293
302
  };
@@ -325,14 +334,30 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
325
334
  contexts.value = entry.contexts ?? {};
326
335
  currentPageId.value = ((_c = entry.page) == null ? void 0 : _c.id) ?? null;
327
336
  setAlternates(navigableAlternates(entry.alternates, path));
337
+ updateDocumentTitle(entry);
328
338
  return true;
329
339
  }
340
+ function contextTitle(contexts2) {
341
+ if (!contexts2) return null;
342
+ const preferredKeys = ["$page", "$post", "$item", "$article", "$product", "$author"];
343
+ const orderedContexts = [
344
+ ...preferredKeys.map((key) => contexts2[key]),
345
+ ...Object.entries(contexts2).filter(([key]) => !preferredKeys.includes(key)).map(([, context]) => context)
346
+ ];
347
+ const titleFields = ["meta_title", "metaTitle", "title", "name", "productName", "displayName"];
348
+ for (const context of orderedContexts) {
349
+ if (!context) continue;
350
+ for (const field of titleFields) {
351
+ const value = context[field];
352
+ if (typeof value === "string" && value.trim()) return value.trim();
353
+ }
354
+ }
355
+ return null;
356
+ }
330
357
  function updateDocumentTitle(resolved) {
358
+ var _a, _b;
331
359
  if (typeof document === "undefined") return;
332
- const { page } = resolved;
333
- const ctx = resolved.contexts ? Object.values(resolved.contexts).find((c) => c != null) : null;
334
- const ctxTitle = ctx && typeof ctx.title === "string" ? ctx.title : null;
335
- const title = page.meta_title || ctxTitle || page.title;
360
+ const title = contextTitle(resolved.contexts) || ((_a = resolved.page) == null ? void 0 : _a.meta_title) || ((_b = resolved.page) == null ? void 0 : _b.title);
336
361
  if (title) document.title = title;
337
362
  }
338
363
  const initialSlug = (() => {
@@ -392,8 +417,107 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
392
417
  const _component_RouterLink = resolveComponent("RouterLink");
393
418
  return openBlock(), createElementBlock("div", null, [
394
419
  initialLoading.value && blocks.value.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_1$1, [
395
- createVNode(unref(Loading))
396
- ])) : notFound.value ? (openBlock(), createElementBlock("div", _hoisted_2$1, [
420
+ createElementVNode("div", _hoisted_2$1, [
421
+ createElementVNode("div", _hoisted_3$1, [
422
+ createVNode(unref(Skeleton), {
423
+ width: "180px",
424
+ height: "42px"
425
+ }),
426
+ createElementVNode("div", _hoisted_4$1, [
427
+ (openBlock(), createElementBlock(Fragment, null, renderList(5, (item) => {
428
+ return createVNode(unref(Skeleton), {
429
+ key: item,
430
+ width: "90px",
431
+ height: "20px"
432
+ });
433
+ }), 64))
434
+ ])
435
+ ]),
436
+ createElementVNode("div", _hoisted_5, [
437
+ createVNode(unref(Skeleton), {
438
+ width: "100%",
439
+ height: "260px"
440
+ }),
441
+ createElementVNode("div", _hoisted_6, [
442
+ createVNode(unref(Skeleton), {
443
+ width: "120px",
444
+ height: "16px",
445
+ class: "mb-1"
446
+ }),
447
+ createVNode(unref(Skeleton), {
448
+ width: "92%",
449
+ height: "34px"
450
+ }),
451
+ createVNode(unref(Skeleton), {
452
+ width: "72%",
453
+ height: "34px",
454
+ class: "mb-1"
455
+ }),
456
+ createVNode(unref(Skeleton), {
457
+ width: "190px",
458
+ height: "16px"
459
+ })
460
+ ])
461
+ ]),
462
+ createElementVNode("div", _hoisted_7, [
463
+ createElementVNode("div", null, [
464
+ createVNode(unref(Skeleton), {
465
+ width: "150px",
466
+ height: "28px",
467
+ class: "mb-1"
468
+ }),
469
+ (openBlock(), createElementBlock(Fragment, null, renderList(3, (tab) => {
470
+ return createVNode(unref(Skeleton), {
471
+ key: tab,
472
+ width: "90px",
473
+ height: "20px",
474
+ class: "mb-1"
475
+ });
476
+ }), 64))
477
+ ]),
478
+ createElementVNode("div", _hoisted_8, [
479
+ (openBlock(), createElementBlock(Fragment, null, renderList(2, (card) => {
480
+ return createElementVNode("div", { key: card }, [
481
+ createVNode(unref(Skeleton), {
482
+ width: "100%",
483
+ height: "210px"
484
+ }),
485
+ createVNode(unref(Skeleton), {
486
+ width: "88%",
487
+ height: "24px",
488
+ class: "mt-05"
489
+ }),
490
+ createVNode(unref(Skeleton), {
491
+ width: "52%",
492
+ height: "15px"
493
+ })
494
+ ]);
495
+ }), 64))
496
+ ])
497
+ ]),
498
+ createElementVNode("div", _hoisted_9, [
499
+ createVNode(unref(Skeleton), {
500
+ width: "100%",
501
+ height: "320px"
502
+ }),
503
+ createElementVNode("div", _hoisted_10, [
504
+ createVNode(unref(Skeleton), {
505
+ width: "220px",
506
+ height: "30px",
507
+ class: "mb-1"
508
+ }),
509
+ (openBlock(), createElementBlock(Fragment, null, renderList(5, (row) => {
510
+ return createVNode(unref(Skeleton), {
511
+ key: row,
512
+ width: "100%",
513
+ height: "58px",
514
+ class: "mb-05"
515
+ });
516
+ }), 64))
517
+ ])
518
+ ])
519
+ ])
520
+ ])) : notFound.value ? (openBlock(), createElementBlock("div", _hoisted_11, [
397
521
  _cache[0] || (_cache[0] = createElementVNode("h2", null, "404", -1)),
398
522
  createElementVNode("p", null, toDisplayString(unref(locale2) === "he" ? "הדף לא נמצא" : "Page not found"), 1),
399
523
  createVNode(_component_RouterLink, { to: "/" }, {
@@ -402,8 +526,8 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
402
526
  ]),
403
527
  _: 1
404
528
  })
405
- ])) : error.value ? (openBlock(), createElementBlock("div", _hoisted_3$1, toDisplayString(error.value), 1)) : (openBlock(), createElementBlock(Fragment, { key: 3 }, [
406
- navigating.value ? (openBlock(), createElementBlock("div", _hoisted_4$1)) : createCommentVNode("", true),
529
+ ])) : error.value ? (openBlock(), createElementBlock("div", _hoisted_12, toDisplayString(error.value), 1)) : (openBlock(), createElementBlock(Fragment, { key: 3 }, [
530
+ navigating.value ? (openBlock(), createElementBlock("div", _hoisted_13)) : createCommentVNode("", true),
407
531
  createVNode(unref(PageRenderer), { blocks: blocks.value }, null, 8, ["blocks"])
408
532
  ], 64)),
409
533
  unref(adminConfig) ? (openBlock(), createBlock(_sfc_main$3, {
@@ -833,7 +957,7 @@ class BloxInstance {
833
957
  }
834
958
  router.addRoute({
835
959
  path: "/_blox_preview",
836
- component: () => import("./PreviewApp-efVmQL4w.js"),
960
+ component: () => import("./PreviewApp-DadFCvv9.js"),
837
961
  beforeEnter: () => window.parent !== window ? true : "/"
838
962
  });
839
963
  router.addRoute({ path: "/:pathMatch(.*)*", component: _sfc_main$2 });
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
25
+ const node_child_process = require("node:child_process");
26
+ const os = require("node:os");
27
+ const path = require("node:path");
28
+ const process = require("node:process");
29
+ const AUTO_SHARD_CAP = Number(process.env.BLOX_SSG_SHARD_CAP) || 6;
30
+ const PREFETCH_BUDGET = Number(process.env.BLOX_SSG_PREFETCH_BUDGET) || 24;
31
+ function resolveShardCount(shards) {
32
+ if (shards === "auto") {
33
+ const cores = os.cpus().length || 4;
34
+ return Math.max(1, Math.min(cores, AUTO_SHARD_CAP));
35
+ }
36
+ return Math.max(1, Math.floor(shards));
37
+ }
38
+ async function enumerateRoutes(cmd) {
39
+ return new Promise((resolve, reject) => {
40
+ const child = node_child_process.spawn(cmd, { shell: true, stdio: ["ignore", "pipe", "inherit"] });
41
+ let out = "";
42
+ child.stdout.on("data", (d) => {
43
+ out += d.toString();
44
+ });
45
+ child.on("error", reject);
46
+ child.on(
47
+ "close",
48
+ (code) => code === 0 ? resolve(out.split(/\s+/).filter(Boolean)) : reject(new Error(`routes-cmd exited ${code}`))
49
+ );
50
+ });
51
+ }
52
+ function runShard(index, total, paths, opts, llmPartsDir) {
53
+ return new Promise((resolve) => {
54
+ const args = [
55
+ `--mode=${opts.mode}`,
56
+ `--shard=${index}/${total}`,
57
+ "--no-crawl",
58
+ `--llm-parts=${path.join(llmPartsDir, `part.${index}.json`)}`,
59
+ ...opts.passthroughArgs,
60
+ ...paths
61
+ ];
62
+ const child = node_child_process.spawn("blox-ssg", args, {
63
+ stdio: ["ignore", "inherit", "inherit"],
64
+ env: {
65
+ ...process.env,
66
+ // Divide the global prefetch budget across shards so N processes
67
+ // don't collectively overwhelm the API.
68
+ BLOX_SSG_PREFETCH: String(Math.max(2, Math.floor(PREFETCH_BUDGET / total)))
69
+ }
70
+ });
71
+ child.on("close", (code) => resolve(code ?? 0));
72
+ child.on("error", (err) => {
73
+ console.error(`[blox-ssg] shard ${index} failed to spawn: ${err.message}`);
74
+ resolve(1);
75
+ });
76
+ });
77
+ }
78
+ async function runSharded(opts) {
79
+ const total = resolveShardCount(opts.shards);
80
+ const paths = [...opts.extraPaths];
81
+ if (opts.routesCmd) {
82
+ const enumerated = await enumerateRoutes(opts.routesCmd);
83
+ for (const p of enumerated) if (!paths.includes(p)) paths.push(p);
84
+ console.log(`[blox-ssg] routes-cmd enumerated ${enumerated.length} route(s)`);
85
+ }
86
+ console.log(`[blox-ssg] sharded run · ${total} shard(s) · ${paths.length} extra path(s)`);
87
+ const llmPartsDir = path.resolve("dist", ".llm-parts");
88
+ await (await import("node:fs/promises")).mkdir(llmPartsDir, { recursive: true }).catch(() => {
89
+ });
90
+ const start = Date.now();
91
+ const codes = total === 1 ? [await runShard(0, 1, paths, opts, llmPartsDir)] : await Promise.all(Array.from({ length: total }, (_, i) => runShard(i, total, paths, opts, llmPartsDir)));
92
+ const failed = codes.findIndex((c) => c !== 0);
93
+ if (failed !== -1) {
94
+ console.error(`[blox-ssg] shard ${failed} exited with code ${codes[failed]}`);
95
+ return codes[failed];
96
+ }
97
+ if (process.env.BLOX_SSG_LLM !== "0") {
98
+ try {
99
+ const [{ mergeLlmParts }, { fetchCmsSiteData }] = await Promise.all([
100
+ Promise.resolve().then(() => require("./prerender-DQ7D6auC.cjs")).then((n) => n.llmArtifacts),
101
+ Promise.resolve().then(() => require("./prerender-DQ7D6auC.cjs")).then((n) => n.cmsRoutes)
102
+ ]);
103
+ let website = null;
104
+ try {
105
+ website = (await fetchCmsSiteData(opts.apiBase, opts.websiteName)).website;
106
+ } catch {
107
+ }
108
+ const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
109
+ const { pages } = await mergeLlmParts({
110
+ partFiles,
111
+ outDir: path.resolve("dist"),
112
+ website,
113
+ config: { fullText: process.env.BLOX_SSG_LLM_FULL !== "0" }
114
+ });
115
+ console.log(`[blox-ssg] merged llms.txt (${pages} pages)`);
116
+ } catch (e) {
117
+ console.warn(`[blox-ssg] llms merge skipped: ${e.message}`);
118
+ }
119
+ }
120
+ console.log(`[blox-ssg] sharded run done in ${((Date.now() - start) / 1e3).toFixed(1)}s`);
121
+ return 0;
122
+ }
123
+ exports.runSharded = runSharded;
@@ -0,0 +1,101 @@
1
+ import { spawn } from "node:child_process";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import process from "node:process";
5
+ const AUTO_SHARD_CAP = Number(process.env.BLOX_SSG_SHARD_CAP) || 6;
6
+ const PREFETCH_BUDGET = Number(process.env.BLOX_SSG_PREFETCH_BUDGET) || 24;
7
+ function resolveShardCount(shards) {
8
+ if (shards === "auto") {
9
+ const cores = os.cpus().length || 4;
10
+ return Math.max(1, Math.min(cores, AUTO_SHARD_CAP));
11
+ }
12
+ return Math.max(1, Math.floor(shards));
13
+ }
14
+ async function enumerateRoutes(cmd) {
15
+ return new Promise((resolve, reject) => {
16
+ const child = spawn(cmd, { shell: true, stdio: ["ignore", "pipe", "inherit"] });
17
+ let out = "";
18
+ child.stdout.on("data", (d) => {
19
+ out += d.toString();
20
+ });
21
+ child.on("error", reject);
22
+ child.on(
23
+ "close",
24
+ (code) => code === 0 ? resolve(out.split(/\s+/).filter(Boolean)) : reject(new Error(`routes-cmd exited ${code}`))
25
+ );
26
+ });
27
+ }
28
+ function runShard(index, total, paths, opts, llmPartsDir) {
29
+ return new Promise((resolve) => {
30
+ const args = [
31
+ `--mode=${opts.mode}`,
32
+ `--shard=${index}/${total}`,
33
+ "--no-crawl",
34
+ `--llm-parts=${path.join(llmPartsDir, `part.${index}.json`)}`,
35
+ ...opts.passthroughArgs,
36
+ ...paths
37
+ ];
38
+ const child = spawn("blox-ssg", args, {
39
+ stdio: ["ignore", "inherit", "inherit"],
40
+ env: {
41
+ ...process.env,
42
+ // Divide the global prefetch budget across shards so N processes
43
+ // don't collectively overwhelm the API.
44
+ BLOX_SSG_PREFETCH: String(Math.max(2, Math.floor(PREFETCH_BUDGET / total)))
45
+ }
46
+ });
47
+ child.on("close", (code) => resolve(code ?? 0));
48
+ child.on("error", (err) => {
49
+ console.error(`[blox-ssg] shard ${index} failed to spawn: ${err.message}`);
50
+ resolve(1);
51
+ });
52
+ });
53
+ }
54
+ async function runSharded(opts) {
55
+ const total = resolveShardCount(opts.shards);
56
+ const paths = [...opts.extraPaths];
57
+ if (opts.routesCmd) {
58
+ const enumerated = await enumerateRoutes(opts.routesCmd);
59
+ for (const p of enumerated) if (!paths.includes(p)) paths.push(p);
60
+ console.log(`[blox-ssg] routes-cmd enumerated ${enumerated.length} route(s)`);
61
+ }
62
+ console.log(`[blox-ssg] sharded run · ${total} shard(s) · ${paths.length} extra path(s)`);
63
+ const llmPartsDir = path.resolve("dist", ".llm-parts");
64
+ await (await import("node:fs/promises")).mkdir(llmPartsDir, { recursive: true }).catch(() => {
65
+ });
66
+ const start = Date.now();
67
+ const codes = total === 1 ? [await runShard(0, 1, paths, opts, llmPartsDir)] : await Promise.all(Array.from({ length: total }, (_, i) => runShard(i, total, paths, opts, llmPartsDir)));
68
+ const failed = codes.findIndex((c) => c !== 0);
69
+ if (failed !== -1) {
70
+ console.error(`[blox-ssg] shard ${failed} exited with code ${codes[failed]}`);
71
+ return codes[failed];
72
+ }
73
+ if (process.env.BLOX_SSG_LLM !== "0") {
74
+ try {
75
+ const [{ mergeLlmParts }, { fetchCmsSiteData }] = await Promise.all([
76
+ import("./prerender-BCRyYSNg.js").then((n) => n.r),
77
+ import("./prerender-BCRyYSNg.js").then((n) => n.q)
78
+ ]);
79
+ let website = null;
80
+ try {
81
+ website = (await fetchCmsSiteData(opts.apiBase, opts.websiteName)).website;
82
+ } catch {
83
+ }
84
+ const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
85
+ const { pages } = await mergeLlmParts({
86
+ partFiles,
87
+ outDir: path.resolve("dist"),
88
+ website,
89
+ config: { fullText: process.env.BLOX_SSG_LLM_FULL !== "0" }
90
+ });
91
+ console.log(`[blox-ssg] merged llms.txt (${pages} pages)`);
92
+ } catch (e) {
93
+ console.warn(`[blox-ssg] llms merge skipped: ${e.message}`);
94
+ }
95
+ }
96
+ console.log(`[blox-ssg] sharded run done in ${((Date.now() - start) / 1e3).toFixed(1)}s`);
97
+ return 0;
98
+ }
99
+ export {
100
+ runSharded
101
+ };
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-jcemLPiq.cjs");
4
+ const cmsRoutes = require("../prerender-DQ7D6auC.cjs");
5
5
  function installFetchTimeout() {
6
6
  const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
7
7
  const original = globalThis.fetch;
@@ -48,12 +48,21 @@ async function main() {
48
48
  let shardIndex = 0;
49
49
  let shardTotal = 1;
50
50
  let llmPartsFile = "";
51
+ let shardsOpt = null;
52
+ let routesCmd = "";
53
+ const passthroughArgs = [];
51
54
  const excludePaths = ["/_blox_preview"];
52
55
  for (const a of argv) {
53
56
  if (a === "--crawl") {
54
57
  crawl = true;
58
+ passthroughArgs.push(a);
55
59
  } else if (a === "--no-crawl") {
56
60
  crawl = false;
61
+ } else if (a.startsWith("--shards=")) {
62
+ const v = a.slice("--shards=".length);
63
+ shardsOpt = v === "auto" ? "auto" : Number.isInteger(Number(v)) ? Number(v) : null;
64
+ } else if (a.startsWith("--routes-cmd=")) {
65
+ routesCmd = a.slice("--routes-cmd=".length);
57
66
  } else if (a.startsWith("--shard=")) {
58
67
  const [i, n] = a.slice("--shard=".length).split("/").map(Number);
59
68
  if (Number.isInteger(i) && Number.isInteger(n) && n > 0 && i >= 0 && i < n) {
@@ -68,29 +77,54 @@ Usage:
68
77
  blox-ssg [options] [extra-paths...]
69
78
 
70
79
  Options:
71
- --mode=<env> Environment from bgl.config.ts (default: production)
72
- --crawl Discover internal links from rendered HTML
73
- --no-crawl Disable crawling (default)
74
- --exclude=<path> Exclude path prefix from rendering
75
- --help, -h Show this help
80
+ --mode=<env> Environment from bgl.config.ts (default: production)
81
+ --crawl Discover internal links from rendered HTML
82
+ --no-crawl Disable crawling (default)
83
+ --exclude=<path> Exclude path prefix from rendering
84
+ --shards=<n|auto> Render in N parallel child processes (auto = min(cores, cap)).
85
+ Avoids the single-process happy-dom leak on large sites and
86
+ parallelizes CPU-bound SSR. Merges each shard's llms parts.
87
+ --shard=<i/n> (internal) Render only this shard's slice — set by --shards.
88
+ --routes-cmd=<cmd> Shell command whose stdout (whitespace-separated) is the
89
+ route list. For router-driven sites with no CMS pages.
90
+ --help, -h Show this help
76
91
 
77
92
  Environment:
78
- BAGELINK_API_URL Override API base URL
79
- WEBSITE_NAME Override CMS website name
93
+ BAGELINK_API_URL Override API base URL
94
+ WEBSITE_NAME Override CMS website name
95
+ BLOX_SSG_SHARD_CAP Cap for --shards=auto (default 6)
96
+ BLOX_SSG_PREFETCH_BUDGET Global /resolve-path prefetch budget across shards (24)
80
97
  `);
81
98
  process.exit(0);
82
99
  } else if (a.startsWith("--mode=")) {
83
100
  mode = a.slice("--mode=".length);
84
101
  } else if (a.startsWith("--exclude=")) {
85
102
  excludePaths.push(a.slice("--exclude=".length));
103
+ passthroughArgs.push(a);
86
104
  } else if (a.startsWith("--llm-parts=")) {
87
105
  llmPartsFile = a.slice("--llm-parts=".length);
88
106
  } else {
89
107
  extraPaths.push(a);
90
108
  }
91
109
  }
110
+ if (shardsOpt !== null || routesCmd) {
111
+ const { apiBase: apiBase2, websiteName: configWebsiteName2 } = await resolveApiBase(mode);
112
+ const websiteName2 = process.env.WEBSITE_NAME ?? configWebsiteName2 ?? "default";
113
+ const { runSharded } = await Promise.resolve().then(() => require("../shard-runner-CZnX4qnn.cjs"));
114
+ const code = await runSharded({
115
+ shards: shardsOpt ?? "auto",
116
+ mode,
117
+ apiBase: apiBase2,
118
+ websiteName: websiteName2,
119
+ extraPaths,
120
+ passthroughArgs,
121
+ routesCmd: routesCmd || void 0
122
+ });
123
+ process.exitCode = code;
124
+ return;
125
+ }
92
126
  const { apiBase, websiteName: configWebsiteName } = await resolveApiBase(mode);
93
- await prerender.polyfillBloxSsgGlobals({ pageUrl: apiBase });
127
+ await cmsRoutes.polyfillBloxSsgGlobals({ pageUrl: apiBase });
94
128
  const websiteName = process.env.WEBSITE_NAME ?? configWebsiteName ?? "default";
95
129
  console.log(`Fetching routes from ${apiBase} (mode: ${mode}, site: ${websiteName})…`);
96
130
  let paths = [];
@@ -99,7 +133,7 @@ Environment:
99
133
  let redirects = [];
100
134
  const collections = {};
101
135
  try {
102
- const siteData = await prerender.fetchCmsSiteData(apiBase, websiteName);
136
+ const siteData = await cmsRoutes.fetchCmsSiteData(apiBase, websiteName);
103
137
  paths = siteData.paths;
104
138
  website = siteData.website;
105
139
  websiteId = siteData.websiteId;
@@ -148,7 +182,7 @@ Environment:
148
182
  }
149
183
  const startTime = Date.now();
150
184
  try {
151
- const result = await prerender.prerender({
185
+ const result = await cmsRoutes.prerender({
152
186
  root: process.cwd(),
153
187
  clientOutDir: "dist",
154
188
  serverEntry: "dist/server/main.server.js",
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-DnqZAE4x.js";
3
+ import { p as polyfillBloxSsgGlobals, f as fetchCmsSiteData, a as prerender } from "../prerender-BCRyYSNg.js";
4
4
  function installFetchTimeout() {
5
5
  const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
6
6
  const original = globalThis.fetch;
@@ -47,12 +47,21 @@ async function main() {
47
47
  let shardIndex = 0;
48
48
  let shardTotal = 1;
49
49
  let llmPartsFile = "";
50
+ let shardsOpt = null;
51
+ let routesCmd = "";
52
+ const passthroughArgs = [];
50
53
  const excludePaths = ["/_blox_preview"];
51
54
  for (const a of argv) {
52
55
  if (a === "--crawl") {
53
56
  crawl = true;
57
+ passthroughArgs.push(a);
54
58
  } else if (a === "--no-crawl") {
55
59
  crawl = false;
60
+ } else if (a.startsWith("--shards=")) {
61
+ const v = a.slice("--shards=".length);
62
+ shardsOpt = v === "auto" ? "auto" : Number.isInteger(Number(v)) ? Number(v) : null;
63
+ } else if (a.startsWith("--routes-cmd=")) {
64
+ routesCmd = a.slice("--routes-cmd=".length);
56
65
  } else if (a.startsWith("--shard=")) {
57
66
  const [i, n] = a.slice("--shard=".length).split("/").map(Number);
58
67
  if (Number.isInteger(i) && Number.isInteger(n) && n > 0 && i >= 0 && i < n) {
@@ -67,27 +76,52 @@ Usage:
67
76
  blox-ssg [options] [extra-paths...]
68
77
 
69
78
  Options:
70
- --mode=<env> Environment from bgl.config.ts (default: production)
71
- --crawl Discover internal links from rendered HTML
72
- --no-crawl Disable crawling (default)
73
- --exclude=<path> Exclude path prefix from rendering
74
- --help, -h Show this help
79
+ --mode=<env> Environment from bgl.config.ts (default: production)
80
+ --crawl Discover internal links from rendered HTML
81
+ --no-crawl Disable crawling (default)
82
+ --exclude=<path> Exclude path prefix from rendering
83
+ --shards=<n|auto> Render in N parallel child processes (auto = min(cores, cap)).
84
+ Avoids the single-process happy-dom leak on large sites and
85
+ parallelizes CPU-bound SSR. Merges each shard's llms parts.
86
+ --shard=<i/n> (internal) Render only this shard's slice — set by --shards.
87
+ --routes-cmd=<cmd> Shell command whose stdout (whitespace-separated) is the
88
+ route list. For router-driven sites with no CMS pages.
89
+ --help, -h Show this help
75
90
 
76
91
  Environment:
77
- BAGELINK_API_URL Override API base URL
78
- WEBSITE_NAME Override CMS website name
92
+ BAGELINK_API_URL Override API base URL
93
+ WEBSITE_NAME Override CMS website name
94
+ BLOX_SSG_SHARD_CAP Cap for --shards=auto (default 6)
95
+ BLOX_SSG_PREFETCH_BUDGET Global /resolve-path prefetch budget across shards (24)
79
96
  `);
80
97
  process.exit(0);
81
98
  } else if (a.startsWith("--mode=")) {
82
99
  mode = a.slice("--mode=".length);
83
100
  } else if (a.startsWith("--exclude=")) {
84
101
  excludePaths.push(a.slice("--exclude=".length));
102
+ passthroughArgs.push(a);
85
103
  } else if (a.startsWith("--llm-parts=")) {
86
104
  llmPartsFile = a.slice("--llm-parts=".length);
87
105
  } else {
88
106
  extraPaths.push(a);
89
107
  }
90
108
  }
109
+ if (shardsOpt !== null || routesCmd) {
110
+ const { apiBase: apiBase2, websiteName: configWebsiteName2 } = await resolveApiBase(mode);
111
+ const websiteName2 = process.env.WEBSITE_NAME ?? configWebsiteName2 ?? "default";
112
+ const { runSharded } = await import("../shard-runner-D4gCfCi3.js");
113
+ const code = await runSharded({
114
+ shards: shardsOpt ?? "auto",
115
+ mode,
116
+ apiBase: apiBase2,
117
+ websiteName: websiteName2,
118
+ extraPaths,
119
+ passthroughArgs,
120
+ routesCmd: routesCmd || void 0
121
+ });
122
+ process.exitCode = code;
123
+ return;
124
+ }
91
125
  const { apiBase, websiteName: configWebsiteName } = await resolveApiBase(mode);
92
126
  await polyfillBloxSsgGlobals({ pageUrl: apiBase });
93
127
  const websiteName = process.env.WEBSITE_NAME ?? configWebsiteName ?? "default";
@@ -22,11 +22,11 @@ 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-jcemLPiq.cjs");
25
+ const cmsRoutes = require("../prerender-DQ7D6auC.cjs");
26
26
  const ssg_client = require("./client.cjs");
27
27
  const pinia = require("pinia");
28
28
  const vue = require("vue");
29
- const routes = require("../routes-CfwE_uYV.cjs");
29
+ const routes = require("../routes-B4RYeiGa.cjs");
30
30
  async function renderBloxSsgPage(options) {
31
31
  var _a, _b, _c;
32
32
  const {
@@ -61,7 +61,7 @@ async function renderBloxSsgPage(options) {
61
61
  const seoOverride = seoHead && Object.keys(seoHead).length > 0 ? seoHead : void 0;
62
62
  const bloxData = dataRegistry && collectData ? collectData(dataRegistry) : {};
63
63
  const dataScript = Object.keys(bloxData).length > 0 ? `<script>window[${JSON.stringify(routes.BLOX_DATA_WINDOW_KEY)}]=${safeJson(bloxData)};${"<"}/script>` : "";
64
- let head = prerender.buildPageHead({
64
+ let head = cmsRoutes.buildPageHead({
65
65
  url,
66
66
  resolvedData,
67
67
  website,
@@ -70,9 +70,9 @@ async function renderBloxSsgPage(options) {
70
70
  stateScript: [stateScript, collectionsScript, websiteIdScript, dataScript].filter(Boolean).join("\n")
71
71
  });
72
72
  const seoData = resolvedData;
73
- const primary = prerender.primaryContextEntry(seoData == null ? void 0 : seoData.contexts);
73
+ const primary = cmsRoutes.primaryContextEntry(seoData == null ? void 0 : seoData.contexts);
74
74
  if ((llm == null ? void 0 : llm.jsonLd) !== false) {
75
- const jsonLd = prerender.buildJsonLd({
75
+ const jsonLd = cmsRoutes.buildJsonLd({
76
76
  url,
77
77
  page: seoData == null ? void 0 : seoData.page,
78
78
  website,
@@ -92,7 +92,7 @@ ${jsonLd}`;
92
92
  url,
93
93
  title,
94
94
  description,
95
- text: (llm == null ? void 0 : llm.fullText) !== false ? prerender.extractPageText(html) : void 0
95
+ text: (llm == null ? void 0 : llm.fullText) !== false ? cmsRoutes.extractPageText(html) : void 0
96
96
  };
97
97
  }
98
98
  const lang = locale || (website == null ? void 0 : website.default_locale) || "en";
@@ -234,21 +234,21 @@ function createBloxSSREntry(options) {
234
234
  }
235
235
  return { render, prefetchResolve };
236
236
  }
237
- exports.buildJsonLd = prerender.buildJsonLd;
238
- exports.buildPageHead = prerender.buildPageHead;
239
- exports.buildSiteHead = prerender.buildSiteHead;
240
- exports.extractPageText = prerender.extractPageText;
241
- exports.fetchCmsPrerenderPaths = prerender.fetchCmsPrerenderPaths;
242
- exports.fetchCmsSiteData = prerender.fetchCmsSiteData;
243
- exports.generateLlmsFullTxt = prerender.generateLlmsFullTxt;
244
- exports.generateLlmsTxt = prerender.generateLlmsTxt;
245
- exports.generateNetlifyRedirects = prerender.generateNetlifyRedirects;
246
- exports.generateRobotsTxt = prerender.generateRobotsTxt;
247
- exports.generateSitemapXml = prerender.generateSitemapXml;
248
- exports.getSiteIconFlags = prerender.getSiteIconFlags;
249
- exports.mergeLlmParts = prerender.mergeLlmParts;
250
- exports.polyfillBloxSsgGlobals = prerender.polyfillBloxSsgGlobals;
251
- exports.prerender = prerender.prerender;
237
+ exports.buildJsonLd = cmsRoutes.buildJsonLd;
238
+ exports.buildPageHead = cmsRoutes.buildPageHead;
239
+ exports.buildSiteHead = cmsRoutes.buildSiteHead;
240
+ exports.extractPageText = cmsRoutes.extractPageText;
241
+ exports.fetchCmsPrerenderPaths = cmsRoutes.fetchCmsPrerenderPaths;
242
+ exports.fetchCmsSiteData = cmsRoutes.fetchCmsSiteData;
243
+ exports.generateLlmsFullTxt = cmsRoutes.generateLlmsFullTxt;
244
+ exports.generateLlmsTxt = cmsRoutes.generateLlmsTxt;
245
+ exports.generateNetlifyRedirects = cmsRoutes.generateNetlifyRedirects;
246
+ exports.generateRobotsTxt = cmsRoutes.generateRobotsTxt;
247
+ exports.generateSitemapXml = cmsRoutes.generateSitemapXml;
248
+ exports.getSiteIconFlags = cmsRoutes.getSiteIconFlags;
249
+ exports.mergeLlmParts = cmsRoutes.mergeLlmParts;
250
+ exports.polyfillBloxSsgGlobals = cmsRoutes.polyfillBloxSsgGlobals;
251
+ exports.prerender = cmsRoutes.prerender;
252
252
  exports.BLOX_COLLECTIONS_WINDOW_KEY = ssg_client.BLOX_COLLECTIONS_WINDOW_KEY;
253
253
  exports.BLOX_DATA_WINDOW_KEY = ssg_client.BLOX_DATA_WINDOW_KEY;
254
254
  exports.BLOX_PAGE_SEO_WINDOW_KEY = ssg_client.BLOX_PAGE_SEO_WINDOW_KEY;
@@ -1,10 +1,10 @@
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";
1
+ import { b as buildPageHead, c as primaryContextEntry, d as buildJsonLd, e as extractPageText } from "../prerender-BCRyYSNg.js";
2
+ import { g, h, f, i, j, k, l, m, n, o, p, a } from "../prerender-BCRyYSNg.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
- 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-D5aVOcFs.js";
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-DE0OIzJr.js";
8
8
  async function renderBloxSsgPage(options) {
9
9
  var _a, _b, _c;
10
10
  const {
@@ -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;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"}
1
+ {"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../../src/ssg/seo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Built-in sharded SSG runner (coordinator).
3
+ *
4
+ * Vue SSR (`renderToString`) is CPU-bound and single-threaded, and a single
5
+ * long-lived `blox-ssg` process also accumulates happy-dom/window/timer state
6
+ * under bun — on large sites (thousands of pages) that leak eventually crashes
7
+ * the process silently. Splitting the work across N short-lived child processes
8
+ * (each rendering a disjoint `--shard=i/n` slice into the same `dist`) both
9
+ * parallelizes the CPU-bound render AND keeps each process well under the leak
10
+ * threshold.
11
+ *
12
+ * This module is the coordinator: it enumerates the route list once (optionally
13
+ * via an external `--routes-cmd` for router-driven sites that don't use CMS page
14
+ * discovery), then spawns the shards, divides the resolve-prefetch budget across
15
+ * them, and merges each shard's llms part file into the final llms.txt.
16
+ *
17
+ * Activated by `--shards=<n|auto>` on the CLI. Without it, the CLI runs a single
18
+ * in-process render exactly as before (full backward compat).
19
+ */
20
+ export interface ShardRunnerOptions {
21
+ /** Number of shards, or 'auto' → min(cores, cap). */
22
+ shards: number | 'auto';
23
+ /** CLI mode (passed through to each shard as --mode=). */
24
+ mode: string;
25
+ /** Resolved API base (for the post-run llms merge). */
26
+ apiBase: string;
27
+ /** CMS website name (for the post-run llms merge). */
28
+ websiteName: string;
29
+ /** Extra paths already parsed from argv (router-driven sites, static routes). */
30
+ extraPaths: string[];
31
+ /** Other pass-through flags to forward verbatim to each shard (e.g. --exclude=…, --crawl). */
32
+ passthroughArgs: string[];
33
+ /**
34
+ * Optional shell command whose stdout (whitespace-separated) is a list of
35
+ * routes to render. Run once by the coordinator; the paths are forwarded to
36
+ * every shard. Lets router-driven sites (no CMS page discovery) enumerate
37
+ * their own routes without a bespoke runner script.
38
+ */
39
+ routesCmd?: string;
40
+ }
41
+ /**
42
+ * Coordinate a sharded prerender. Returns the process exit code.
43
+ */
44
+ export declare function runSharded(opts: ShardRunnerOptions): Promise<number>;
45
+ //# sourceMappingURL=shard-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shard-runner.d.ts","sourceRoot":"","sources":["../../src/ssg/shard-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AASH,MAAM,WAAW,kBAAkB;IAClC,qDAAqD;IACrD,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAA;IACf,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAA;IACnB,iFAAiF;IACjF,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,8FAA8F;IAC9F,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AAyDD;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0D1E"}
@@ -265,7 +265,7 @@ function bloxPlugin(options = {}) {
265
265
  const blockName = nameMatch[1];
266
266
  const exportName = blockName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
267
267
  remaining = remaining.slice(0, callStart) + remaining.slice(i);
268
- const scannable = callExpr.replace(/'(?:\\.|[^'\\])*'/g, "''").replace(/"(?:\\.|[^"\\])*"/g, '""').replace(/`(?:\\.|[^`\\])*`/g, "``").replace(/\.\s*[a-z_$][\w$]*/gi, "").replace(/([a-z_$][\w$]*)\s*:/gi, ":");
268
+ const scannable = callExpr.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "").replace(/'(?:\\.|[^'\\])*'/g, "''").replace(/"(?:\\.|[^"\\])*"/g, '""').replace(/`(?:\\.|[^`\\])*`/g, "``").replace(/\.\s*[a-z_$][\w$]*/gi, "").replace(/([a-z_$][\w$]*)\s*:/gi, ":");
269
269
  const identifiers = /* @__PURE__ */ new Set();
270
270
  const identRe = /\b([a-z_$][\w$]*)\b/gi;
271
271
  let identMatch;
@@ -283,7 +283,7 @@ function bloxPlugin(options = {}) {
283
283
  const declaredIdents = /* @__PURE__ */ new Set();
284
284
  const queue = [...identifiers].filter((id2) => id2 !== "defineBlock");
285
285
  const refsIn = (src) => {
286
- const scan = src.replace(/'(?:\\.|[^'\\])*'/g, "''").replace(/"(?:\\.|[^"\\])*"/g, '""').replace(/`(?:\\.|[^`\\])*`/g, "``").replace(/\.\s*[a-z_$][\w$]*/gi, "").replace(/([a-z_$][\w$]*)\s*:/gi, ":");
286
+ const scan = src.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "").replace(/'(?:\\.|[^'\\])*'/g, "''").replace(/"(?:\\.|[^"\\])*"/g, '""').replace(/`(?:\\.|[^`\\])*`/g, "``").replace(/\.\s*[a-z_$][\w$]*/gi, "").replace(/([a-z_$][\w$]*)\s*:/gi, ":");
287
287
  const out = [];
288
288
  let m;
289
289
  const re = /\b([a-z_$][\w$]*)\b/gi;
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,MAAM,CAAA;AAM9C,MAAM,WAAW,iBAAiB;IACjC;;;;;OAKG;IACH,GAAG,CAAC,EAAE,OAAO,CAAA;IACb;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,EAAE,CA8dpE"}
1
+ {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,MAAM,CAAA;AAM9C,MAAM,WAAW,iBAAiB;IACjC;;;;;OAKG;IACH,GAAG,CAAC,EAAE,OAAO,CAAA;IACb;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,EAAE,CAyepE"}
@@ -241,7 +241,7 @@ function bloxPlugin(options = {}) {
241
241
  const blockName = nameMatch[1];
242
242
  const exportName = blockName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
243
243
  remaining = remaining.slice(0, callStart) + remaining.slice(i);
244
- const scannable = callExpr.replace(/'(?:\\.|[^'\\])*'/g, "''").replace(/"(?:\\.|[^"\\])*"/g, '""').replace(/`(?:\\.|[^`\\])*`/g, "``").replace(/\.\s*[a-z_$][\w$]*/gi, "").replace(/([a-z_$][\w$]*)\s*:/gi, ":");
244
+ const scannable = callExpr.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "").replace(/'(?:\\.|[^'\\])*'/g, "''").replace(/"(?:\\.|[^"\\])*"/g, '""').replace(/`(?:\\.|[^`\\])*`/g, "``").replace(/\.\s*[a-z_$][\w$]*/gi, "").replace(/([a-z_$][\w$]*)\s*:/gi, ":");
245
245
  const identifiers = /* @__PURE__ */ new Set();
246
246
  const identRe = /\b([a-z_$][\w$]*)\b/gi;
247
247
  let identMatch;
@@ -259,7 +259,7 @@ function bloxPlugin(options = {}) {
259
259
  const declaredIdents = /* @__PURE__ */ new Set();
260
260
  const queue = [...identifiers].filter((id2) => id2 !== "defineBlock");
261
261
  const refsIn = (src) => {
262
- const scan = src.replace(/'(?:\\.|[^'\\])*'/g, "''").replace(/"(?:\\.|[^"\\])*"/g, '""').replace(/`(?:\\.|[^`\\])*`/g, "``").replace(/\.\s*[a-z_$][\w$]*/gi, "").replace(/([a-z_$][\w$]*)\s*:/gi, ":");
262
+ const scan = src.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "").replace(/'(?:\\.|[^'\\])*'/g, "''").replace(/"(?:\\.|[^"\\])*"/g, '""').replace(/`(?:\\.|[^`\\])*`/g, "``").replace(/\.\s*[a-z_$][\w$]*/gi, "").replace(/([a-z_$][\w$]*)\s*:/gi, ":");
263
263
  const out = [];
264
264
  let m;
265
265
  const re = /\b([a-z_$][\w$]*)\b/gi;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/blox",
3
3
  "type": "module",
4
- "version": "1.15.271",
4
+ "version": "1.15.275",
5
5
  "description": "Blox page builder library for drag-and-drop page building and static data management",
6
6
  "author": {
7
7
  "name": "Bagel Studio",