@bagelink/blox 1.17.4 → 1.17.6

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.
@@ -26,7 +26,7 @@ const node_child_process = require("node:child_process");
26
26
  const os = require("node:os");
27
27
  const path = require("node:path");
28
28
  const process = require("node:process");
29
- const llmArtifacts = require("./validate-output-CffqejmL.cjs");
29
+ const llmArtifacts = require("./validate-output-C94Qpxw3.cjs");
30
30
  const AUTO_SHARD_CAP = Number(process.env.BLOX_SSG_SHARD_CAP) || 6;
31
31
  const PREFETCH_BUDGET = Number(process.env.BLOX_SSG_PREFETCH_BUDGET) || 24;
32
32
  const SEQUENTIAL_SHARDS = process.env.BLOX_SSG_SEQUENTIAL === "1";
@@ -166,7 +166,7 @@ async function runSharded(opts) {
166
166
  }
167
167
  if (process.env.BLOX_SSG_LLM !== "0") {
168
168
  try {
169
- const { mergeLlmParts } = await Promise.resolve().then(() => require("./validate-output-CffqejmL.cjs")).then((n) => n.llmArtifacts);
169
+ const { mergeLlmParts } = await Promise.resolve().then(() => require("./validate-output-C94Qpxw3.cjs")).then((n) => n.llmArtifacts);
170
170
  const mergeWebsite = website;
171
171
  const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
172
172
  const { pages } = await mergeLlmParts({
@@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import process from "node:process";
5
- import { f as fetchCmsSiteData, g as generateSitemapArtifacts } from "./validate-output-BfVBOndk.js";
5
+ import { f as fetchCmsSiteData, g as generateSitemapArtifacts } from "./validate-output-CuX33CnX.js";
6
6
  const AUTO_SHARD_CAP = Number(process.env.BLOX_SSG_SHARD_CAP) || 6;
7
7
  const PREFETCH_BUDGET = Number(process.env.BLOX_SSG_PREFETCH_BUDGET) || 24;
8
8
  const SEQUENTIAL_SHARDS = process.env.BLOX_SSG_SEQUENTIAL === "1";
@@ -142,7 +142,7 @@ async function runSharded(opts) {
142
142
  }
143
143
  if (process.env.BLOX_SSG_LLM !== "0") {
144
144
  try {
145
- const { mergeLlmParts } = await import("./validate-output-BfVBOndk.js").then((n) => n.C);
145
+ const { mergeLlmParts } = await import("./validate-output-CuX33CnX.js").then((n) => n.C);
146
146
  const mergeWebsite = website;
147
147
  const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
148
148
  const { pages } = await mergeLlmParts({
package/dist/ssg/cli.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  const process = require("node:process");
4
4
  const fs = require("node:fs/promises");
5
5
  const ssg_buildGrant = require("./build-grant.cjs");
6
- const llmArtifacts = require("../validate-output-CffqejmL.cjs");
6
+ const llmArtifacts = require("../validate-output-C94Qpxw3.cjs");
7
7
  function installFetchTimeout() {
8
8
  const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
9
9
  const original = globalThis.fetch;
@@ -147,7 +147,7 @@ Environment:
147
147
  if (shardsOpt !== null || routesCmd) {
148
148
  const { apiBase: apiBase2, websiteName: configWebsiteName2 } = await resolveApiBase(mode);
149
149
  const websiteName2 = process.env.WEBSITE_NAME ?? configWebsiteName2 ?? "default";
150
- const { runSharded } = await Promise.resolve().then(() => require("../shard-runner-Dj9D4os0.cjs"));
150
+ const { runSharded } = await Promise.resolve().then(() => require("../shard-runner-DXjScXLk.cjs"));
151
151
  const code = await runSharded({
152
152
  shards: shardsOpt ?? "auto",
153
153
  mode,
package/dist/ssg/cli.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import process from "node:process";
3
3
  import fs from "node:fs/promises";
4
4
  import { resolveBloxBuildGrant } from "./build-grant.mjs";
5
- import { v as validateSsgOutput, u as uploadBloxManifest, p as polyfillBloxSsgGlobals, f as fetchCmsSiteData, b as buildCollectionResolver, a as prerender, c as validateInternalLinks } from "../validate-output-BfVBOndk.js";
5
+ import { v as validateSsgOutput, u as uploadBloxManifest, p as polyfillBloxSsgGlobals, f as fetchCmsSiteData, b as buildCollectionResolver, a as prerender, c as validateInternalLinks } from "../validate-output-CuX33CnX.js";
6
6
  function installFetchTimeout() {
7
7
  const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
8
8
  const original = globalThis.fetch;
@@ -146,7 +146,7 @@ Environment:
146
146
  if (shardsOpt !== null || routesCmd) {
147
147
  const { apiBase: apiBase2, websiteName: configWebsiteName2 } = await resolveApiBase(mode);
148
148
  const websiteName2 = process.env.WEBSITE_NAME ?? configWebsiteName2 ?? "default";
149
- const { runSharded } = await import("../shard-runner-DblUxj8s.js");
149
+ const { runSharded } = await import("../shard-runner-f05p1VMY.js");
150
150
  const code = await runSharded({
151
151
  shards: shardsOpt ?? "auto",
152
152
  mode,
@@ -22,7 +22,7 @@ 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 llmArtifacts = require("../validate-output-CffqejmL.cjs");
25
+ const llmArtifacts = require("../validate-output-C94Qpxw3.cjs");
26
26
  const ssg_buildGrant = require("./build-grant.cjs");
27
27
  const ssg_client = require("../client-AoDTJJXJ.cjs");
28
28
  const vue = require("vue");
@@ -1,5 +1,5 @@
1
- import { d as buildPageHead, e as primaryContextEntry, h as buildJsonLd, i as extractPageText, B as BloxBuildResponseError, j as bloxBuildJson } from "../validate-output-BfVBOndk.js";
2
- import { k, l, f, m, n, o, q, g, r, s, t, w, x, y, p, a, z, A, u, c, v } from "../validate-output-BfVBOndk.js";
1
+ import { d as buildPageHead, e as primaryContextEntry, h as buildJsonLd, i as extractPageText, B as BloxBuildResponseError, j as bloxBuildJson } from "../validate-output-CuX33CnX.js";
2
+ import { k, l, f, m, n, o, q, g, r, s, t, w, x, y, p, a, z, A, u, c, v } from "../validate-output-CuX33CnX.js";
3
3
  import { parseBloxBuildGrantBody, resolveBloxBuildGrant } from "./build-grant.mjs";
4
4
  import { a as BLOX_HYDRATION_WINDOW_KEY } from "../client-Ce9fRCGH.js";
5
5
  import { createSSRApp, h, Suspense } from "vue";
@@ -10,6 +10,12 @@ export declare function validateInternalLinks(outDir: string): Promise<void>;
10
10
  export interface ValidateSsgOutputOptions {
11
11
  outDir: string;
12
12
  requireFiles?: string[];
13
+ /**
14
+ * Require generated `/assets/*.css|js` references to contain a content hash.
15
+ * Enable when those files are served with long-lived immutable caching.
16
+ * @default true for Blox SSG output validation
17
+ */
18
+ requireHashedAssets?: boolean;
13
19
  /**
14
20
  * Fail when a prerendered page contains a relative internal link.
15
21
  *
@@ -1 +1 @@
1
- {"version":3,"file":"validate-output.d.ts","sourceRoot":"","sources":["../../src/ssg/validate-output.ts"],"names":[],"mappings":"AASA;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBzE;AAED,MAAM,WAAW,wBAAwB;IACxC,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC5B;AAgCD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiExF"}
1
+ {"version":3,"file":"validate-output.d.ts","sourceRoot":"","sources":["../../src/ssg/validate-output.ts"],"names":[],"mappings":"AAWA;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBzE;AAED,MAAM,WAAW,wBAAwB;IACxC,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC5B;AAgCD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2ExF"}
@@ -1518,6 +1518,8 @@ const sitemapIndexEntry = /<sitemap>\s*<loc>[^<]+<\/loc>/gm;
1518
1518
  const sitemapLoc = /<loc>([^<]+)<\/loc>/;
1519
1519
  const loadingShell = /class=["'][^"']*\bblox-initial-loading\b/;
1520
1520
  const embeddedCmsState = /\b__BLOX_HYDRATION__\b/;
1521
+ const generatedAssetRef = /<(?:script|link)\b[^>]*(?:src|href)=["']([^"']+)["'][^>]*>/gi;
1522
+ const contentHash = /-[A-Za-z0-9_-]{6,}\.(?:css|js)$/;
1521
1523
  async function validateInternalLinks(outDir) {
1522
1524
  const root = path.resolve(outDir);
1523
1525
  const failures = [];
@@ -1554,6 +1556,7 @@ async function validateSsgOutput(options) {
1554
1556
  const outDir = path.resolve(options.outDir);
1555
1557
  const failures = [];
1556
1558
  const checkInternalLinks = options.checkInternalLinks ?? true;
1559
+ const requireHashedAssets = options.requireHashedAssets ?? true;
1557
1560
  const requiredFiles = options.requireFiles ?? [
1558
1561
  "robots.txt",
1559
1562
  "_redirects",
@@ -1575,6 +1578,13 @@ async function validateSsgOutput(options) {
1575
1578
  if (loadingShell.test(html) && !embeddedCmsState.test(html)) {
1576
1579
  failures.push(`${name}: contains only the Blox loading shell`);
1577
1580
  }
1581
+ if (requireHashedAssets) {
1582
+ for (const asset of unhashedGeneratedAssets(html)) {
1583
+ failures.push(
1584
+ `${name}: generated asset "${asset}" is not content-hashed, but Blox sites serve /assets/* with immutable caching. Use an asset filename containing -[hash] before .css/.js.`
1585
+ );
1586
+ }
1587
+ }
1578
1588
  if (checkInternalLinks) {
1579
1589
  for (const href of relativeInternalLinks(html)) {
1580
1590
  failures.push(
@@ -1609,6 +1619,17 @@ async function validateSsgOutput(options) {
1609
1619
  ${failures.map((item) => ` - ${item}`).join("\n")}`);
1610
1620
  }
1611
1621
  }
1622
+ function unhashedGeneratedAssets(html) {
1623
+ var _a;
1624
+ const found = /* @__PURE__ */ new Set();
1625
+ for (const match of html.matchAll(generatedAssetRef)) {
1626
+ const value = ((_a = match[1]) == null ? void 0 : _a.trim()) ?? "";
1627
+ const pathname = value.split(/[?#]/, 1)[0];
1628
+ if (!pathname.startsWith("/assets/") || !/\.(?:css|js)$/.test(pathname)) continue;
1629
+ if (!contentHash.test(pathname)) found.add(pathname);
1630
+ }
1631
+ return [...found];
1632
+ }
1612
1633
  function relativeInternalLinks(html) {
1613
1634
  var _a;
1614
1635
  const found = /* @__PURE__ */ new Set();
@@ -1495,6 +1495,8 @@ const sitemapIndexEntry = /<sitemap>\s*<loc>[^<]+<\/loc>/gm;
1495
1495
  const sitemapLoc = /<loc>([^<]+)<\/loc>/;
1496
1496
  const loadingShell = /class=["'][^"']*\bblox-initial-loading\b/;
1497
1497
  const embeddedCmsState = /\b__BLOX_HYDRATION__\b/;
1498
+ const generatedAssetRef = /<(?:script|link)\b[^>]*(?:src|href)=["']([^"']+)["'][^>]*>/gi;
1499
+ const contentHash = /-[A-Za-z0-9_-]{6,}\.(?:css|js)$/;
1498
1500
  async function validateInternalLinks(outDir) {
1499
1501
  const root = path.resolve(outDir);
1500
1502
  const failures = [];
@@ -1531,6 +1533,7 @@ async function validateSsgOutput(options) {
1531
1533
  const outDir = path.resolve(options.outDir);
1532
1534
  const failures = [];
1533
1535
  const checkInternalLinks = options.checkInternalLinks ?? true;
1536
+ const requireHashedAssets = options.requireHashedAssets ?? true;
1534
1537
  const requiredFiles = options.requireFiles ?? [
1535
1538
  "robots.txt",
1536
1539
  "_redirects",
@@ -1552,6 +1555,13 @@ async function validateSsgOutput(options) {
1552
1555
  if (loadingShell.test(html) && !embeddedCmsState.test(html)) {
1553
1556
  failures.push(`${name}: contains only the Blox loading shell`);
1554
1557
  }
1558
+ if (requireHashedAssets) {
1559
+ for (const asset of unhashedGeneratedAssets(html)) {
1560
+ failures.push(
1561
+ `${name}: generated asset "${asset}" is not content-hashed, but Blox sites serve /assets/* with immutable caching. Use an asset filename containing -[hash] before .css/.js.`
1562
+ );
1563
+ }
1564
+ }
1555
1565
  if (checkInternalLinks) {
1556
1566
  for (const href of relativeInternalLinks(html)) {
1557
1567
  failures.push(
@@ -1586,6 +1596,17 @@ async function validateSsgOutput(options) {
1586
1596
  ${failures.map((item) => ` - ${item}`).join("\n")}`);
1587
1597
  }
1588
1598
  }
1599
+ function unhashedGeneratedAssets(html) {
1600
+ var _a;
1601
+ const found = /* @__PURE__ */ new Set();
1602
+ for (const match of html.matchAll(generatedAssetRef)) {
1603
+ const value = ((_a = match[1]) == null ? void 0 : _a.trim()) ?? "";
1604
+ const pathname = value.split(/[?#]/, 1)[0];
1605
+ if (!pathname.startsWith("/assets/") || !/\.(?:css|js)$/.test(pathname)) continue;
1606
+ if (!contentHash.test(pathname)) found.add(pathname);
1607
+ }
1608
+ return [...found];
1609
+ }
1589
1610
  function relativeInternalLinks(html) {
1590
1611
  var _a;
1591
1612
  const found = /* @__PURE__ */ new Set();
@@ -80,7 +80,7 @@ function bloxPlugin(options = {}) {
80
80
  };
81
81
  if (command === "build") {
82
82
  const output = (_b = (_a = config.build) == null ? void 0 : _a.rollupOptions) == null ? void 0 : _b.output;
83
- const assetFileNames = "assets/[name][extname]";
83
+ const assetFileNames = "assets/[name]-[hash][extname]";
84
84
  ssrConfig.build = {
85
85
  rollupOptions: {
86
86
  output: Array.isArray(output) ? output.map((item) => ({ assetFileNames, ...item })) : { assetFileNames, ...output }
@@ -3,7 +3,7 @@ export interface BloxPluginOptions {
3
3
  /**
4
4
  * Enable SSR-aware config injection.
5
5
  * When true, adds `resolve.dedupe`, `resolve.alias` for Vue,
6
- * SSR build rollup options, and stable local asset filenames automatically.
6
+ * SSR build rollup options, and content-hashed build asset filenames.
7
7
  * @default false
8
8
  */
9
9
  ssr?: boolean;
@@ -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;;;;;;;;;;;;;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;;;;;;;;;;;;;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,CAiepE"}
@@ -56,7 +56,7 @@ function bloxPlugin(options = {}) {
56
56
  };
57
57
  if (command === "build") {
58
58
  const output = (_b = (_a = config.build) == null ? void 0 : _a.rollupOptions) == null ? void 0 : _b.output;
59
- const assetFileNames = "assets/[name][extname]";
59
+ const assetFileNames = "assets/[name]-[hash][extname]";
60
60
  ssrConfig.build = {
61
61
  rollupOptions: {
62
62
  output: Array.isArray(output) ? output.map((item) => ({ assetFileNames, ...item })) : { assetFileNames, ...output }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/blox",
3
3
  "type": "module",
4
- "version": "1.17.4",
4
+ "version": "1.17.6",
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",